Как мне получить поле DocumentReference из Firestore?

#java #firebase #google-cloud-firestore

#java #firebase #google-облако-firestore

Вопрос:

Я пытаюсь извлечь объект из Google Firestore, это объект:

Объект Firestore

Поскольку я добавил атрибут, поэтому я получаю ошибки, я использую этот класс для десериализации объекта:

 @Data
public class Car {
    private String plate;
    private String model;
    private long km;
    private boolean available;
    private DocumentReference soat;   
}
  

И этот код для извлечения всех объектов Car из Firestore

      @Override
    public List<Car> findAll() {
        List<Car> empList = new ArrayList<Car>();
        CollectionReference car = fb.getFirestore().collection("Cars");
        ApiFuture<QuerySnapshot> querySnapshot = car.get();
        try {
            for (DocumentSnapshot doc : querySnapshot.get().getDocuments()) {
                Car emp = doc.toObject(Car.class);
                empList.add(emp);
            }
        } catch (Exception e) {
             e.printStackTrace();
        }
        return empList;
    }
  

Поскольку я добавил свойство, я получаю эту ошибку при запросе данных

ОШИБКА 7544 — [nio-8080-exec-7], например, ошибка vcautoconfiguration $StaticView: не удается отобразить страницу ошибки для запроса [маршрут запроса] и исключения [Не удалось записать JSON: бесконечная рекурсия (StackOverflowError); вложенным исключением является com.fasterxml.jackson.databind .Исключение JsonMappingException: бесконечная рекурсия (StackOverflowError) (через цепочку ссылок: com.google.cloud.firestore.FirestoreImpl[«параметры»] ->com.google.cloud.firestore.FirestoreOptions[«сервис»] ->com.google.cloud.firestore.FirestoreImpl[«параметры»] ->com.google.cloud.firestore.FirestoreOptions[«сервис»] ->com.google.cloud.firestore.FirestoreImpl[«параметры»] ->com.google.cloud.firestore.FirestoreOptions[«сервис»] ->com.google.cloud.firestore.FirestoreImpl[«параметры»]… -> com.google.cloud.firestore.FirestoreOptions[«credentia [«modulus»])] поскольку ответ уже был зафиксирован. В результате,

Ранее я не мог правильно выполнить запрос, поэтому я добавил это в свой application.properties

 spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
  

Редактировать: просто попробовал этот подход и все еще получаю ту же ошибку

     @Override
    public List<Car> findAll() {
        List<Car> empList = new ArrayList<Car>();
        CollectionReference car = fb.getFirestore().collection("Cars");
        ApiFuture<QuerySnapshot> querySnapshot = car.get();
        try {
            for (DocumentSnapshot doc : querySnapshot.get().getDocuments()) {
               
                 String plate=doc.getData().get("plate").toString();
                 String model=doc.getData().get("model").toString();
                 long km=Long.parseLong(doc.getData().get("km").toString());
                 boolean available=Boolean.parseBoolean(doc.getData().get("available").toString());
                 DocumentReference soat=(DocumentReference)doc.getData().get("soat");

                Car emp = new Car();
                emp.setAvailable(available);
                emp.setKm(km);
                emp.setModel(model);
                emp.setPlate(plate);
                emp.setSoat(soat);

                empList.add(emp);
            }
        } catch (Exception e) {
             e.printStackTrace();
        }
        return empList;
    }
  

——-РЕДАКТИРОВАТЬ———
Я добавил это в свой application.properties

 spring.jackson.serialization.fail-on-self-references=false
  

И теперь я получаю это из вызова Firestore

 [{"plate":"HEO628","model":"2014","km":75000,"available":true,"soat":{"path":"SOATS/HEO628","parent":{"parent":null,"id":"SOATS","path":"SOATS","firestore":{"firestore":{"firestore":{"firestore":{"firestore":{"firestore":{"firestore":{"firestore":{"firestore":
  

Комментарии:

1. Возможно, вы захотите попробовать просто извлекать каждое поле из моментального снимка по отдельности вместо использования ToObject.

2. просто попробовал, все равно получаю ту же ошибку, спасибо за вашу помощь в любом случае

3. Можете ли вы показать код, в котором вы получаете отдельное soat поле, и ошибку, которую вы получаете в этом случае. Я не уверен, как это приведет StackOverflowError к.

4. Car emp = doc.toObject(Car.class); когда я использую эту часть кода, он извлекает всю информацию из объекта Firebase, показанного на первом изображении, и сопоставляет ее с помощью Car класса, поэтому я никогда не получаю ее по soat отдельности.

Ответ №1:

По сути, вам нужно создать класс для десериализации вашей ссылки DatabaseReference, в этом случае имя класса будет SOAT и использовать его для создания вашей ссылки на базу данных.

 @Data
public class Car {
    private String plate;
    private String model;
    private long km;
    private boolean available;
    private SOAT soat;  
    private Insurance insurance;
    private Techno techno;
}
  

Затем при получении информации из FireBase вы должны выполнить следующие запросы, чтобы указать тип объекта, который вы собираетесь сопоставить.

 public List<Car> findAll() {
        List<Car> empList = new ArrayList<Car>();
        CollectionReference car = fb.getFirestore().collection("Cars");
        ApiFuture<QuerySnapshot> querySnapshot = car.get();
        try {
            for (DocumentSnapshot doc : querySnapshot.get().getDocuments()) {

                String plate = doc.getData().get("plate").toString();
                String model = doc.getData().get("model").toString();
                long km = Long.parseLong(doc.getData().get("km").toString());
                boolean available = Boolean.parseBoolean(doc.getData().get("available").toString());
                DocumentSnapshot soatref = fb.getFirestore().collection("SOATS").document(plate).get().get();
                DocumentSnapshot technoref = fb.getFirestore().collection("Technos").document(plate).get().get();
                DocumentSnapshot insuranceref = fb.getFirestore().collection("Insurances").document(plate).get().get();
                SOAT soat = soatref.toObject(SOAT.class);
                Techno techno = technoref.toObject(Techno.class);
                Insurance insurance = insuranceref.toObject(Insurance.class);

                Car emp = new Car();
                emp.setAvailable(available);
                emp.setKm(km);
                emp.setModel(model);
                emp.setPlate(plate);
                emp.setSoat(soat);
                emp.setInsurance(insurance);
                emp.setTechno(techno);

                empList.add(emp);
            }
        } catch (Exception e) {

        }
        return empList;
    }
  

Затем при вызове вашего API вы должны получить правильную ссылку на объект, подобный этому.

 {
    "plate": "HEO628",
    "model": "2014",
    "km": 75000,
    "available": true,
    "soat": {
      "expeditionDate": "2020-09-29T06:12:12.000 00:00",
      "carPlate": "HEO628"
    },
    "insurance": {
      "expeditionDate": "2020-10-01T11:12:12.000 00:00",
      "carPlate": "HEO628"
    },
    "techno": {
      "expeditionDate": "2020-09-08T17:00:00.000 00:00",
      "carPlate": "HEO628"
    }
  }