Hibernate OGM с Mongodb Результат 2-го запроса в той же таблице зависит от полей результатов 1-го запроса той же таблицы

Я использую Hibernate OGM (5.2.0.Alpha1) с Mongodb (3.4)

@Entity
@Table(name = "service")
@JsonInclude(Include.NON_EMPTY)
public class Service {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "SERVICE_ID", unique = true, nullable = false)
    @JsonSerialize(using = ToStringSerializer.class)
    public ObjectId id;

    private String name;

    @ManyToOne
    @JsonIgnore
    public Lab lab;

    getter....
    setter....
}

@Entity
@Table(name = "lab")
@JsonInclude(Include.NON_EMPTY)
// @JsonFilter(value=SalesUtils.MY_CUSTOM_FILTER_FOR_LAB)
public class Lab {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonSerialize(using = ToStringSerializer.class)
    @Column(name = "LAB_ID", unique = true, nullable = false)
    public ObjectId id;

    private String name;

    @OneToMany(mappedBy = "lab")
    public List<Service> listOfServices;

    getter....
    setter....
}

Слой Дао:

public <T> List<T> executeQuery(String query, Integer startPosition, Integer noOfRecords, T t) {
        List<T> listOfT = new ArrayList<>();

        if (SalesUtils.isObjectisNullOrEmpty(startPosition, noOfRecords)) {
            listOfT = entityManager.createNativeQuery(query.toString(), t.getClass()).getResultList();
        } else {
            listOfT = entityManager.createNativeQuery(query.toString(), t.getClass()).setFirstResult(startPosition)
                    .setMaxResults(noOfRecords).getResultList();
        }
        return SalesUtils.isListIsNullOrEmpty(listOfT) ? new ArrayList<>() : listOfT;
    }

Сервисный уровень: (Проблема: имя лаборатории: ноль)

@Transaction
public void executeQuery(){

    String query = "db.service.find({} , {"name":1})";
    List<Service> listOfServices = myDao.executeQuery(query , null , null ,new Service());

    String anotherQuery = " { $query : { name : "CDG Service"}}";
    List<Service> listOfAnotherServices = myDao.executeQuery(query , null , null ,new Service());

    if (!SalesUtils.isListIsNullOrEmpty(listOfAnotherServices )) {
        System.out.println(listOfAnotherServices.get(0).getName());
        System.out.println(listOfAnotherServices.get(0).getLab().getName()); //null 
    }
}

Сервисный уровень: (временное решение)

 @Transaction
    public void executeQuery(){
        //Temporary solution : added lab_LAB_ID field in below 1st query
        String query = "db.service.find({} , {"name":1,"lab_LAB_ID":1})";
        List<Service> listOfServices = myDao.executeQuery(query , null , null ,new Service());

        String anotherQuery = " { $query : { name : "CDG Service"}}";
        List<Service> listOfAnotherServices = myDao.executeQuery(query , null , null ,new Service());

        if (!SalesUtils.isListIsNullOrEmpty(listOfAnotherServices )) {
            System.out.println(listOfAnotherServices.get(0).getName());
            System.out.println(listOfAnotherServices.get(0).getLab().getName()); //not null
        }
    }

Подробное объяснение:

  1. Сервисный уровень: (Проблема: имя лаборатории: ноль)

Здесь я получаю только поле «имя» таблицы обслуживания, используя выполнение 1-го запроса (имя переменной = запрос), а затем выполняю 2-й запрос (имя переменной = другой запрос), но не могу получить лабораторный объект.

  1. Сервисный уровень: (временное решение)

поэтому я получаю «имя» и «lab_LAB_ID» в обоих полях, используя выполнение 1-го запроса (имя переменной = запрос), а затем я выполняю 2-й запрос (имя переменной = другой запрос), поэтому я не могу успешно получить лабораторный объект.

Я этого не понимаю. Похоже, что результат второго запроса зависит от полей результатов первого запроса, даже если запрос отличается, и имя переменной также отличается.

Я прав?


person vishvas4u    schedule 17.01.2018    source источник


Ответы (2)


Используя собственные запросы, если вы решите применить проекцию к корневому классу, вы должны удалить toEntity, потому что частичное извлечение сущности не должно быть разрешено. Вполне вероятно, что в следующих версиях продукта будет введено генерирование исключений, чтобы предотвратить такое использование. Это текущее поведение Hibernate ORM (5.2 | 5.3) и на диалекте H2.

person fax4ever    schedule 07.03.2018

РЕДАКТИРОВАТЬ: Проблема в том, что результаты первых запросов кэшируются (на уровне сеанса), а затем повторно используются во втором запросе. Поскольку исходный запрос, который вы запускаете, не возвращает все поля, сущность инициализируется лишь частично. Обязательно верните все поля, если вы хотите воссоздать объект. Hibernate OGM должен вызывать исключение, когда пользователь пытается воссоздать объект только с подмножеством свойств. Для этого я создам новую JIRA.

Когда вы указываете {name: 1}, вы просите вернуть только следующие поля: _id и name; Поскольку вы запросили услугу, Hibernate OGM преобразует эти значения в класс службы. Проблема в том, что результат не содержит лаборатории, и поэтому это поле пустое (вместо этого должно быть исключение).

Когда вы запускаете db.service.find({} , {"name":1,"lab_LAB_ID":1}), вы также возвращаете идентификатор лаборатории, с этой дополнительной информацией OGM также сможет добавить лабораторию в службу.

Собственный запрос, который вы должны использовать, если вам нужен весь сервис:

    String query = "db.service.find({})";

Но я бы рекомендовал HQL-запрос для этого сценария:

    String hqlQuery = "FROM Service";
    List<Service> services = entityManager.createQuery(hqlQuery, Service.class)
                                          .getResultList();

Кстати, вам не нужно создавать новый Service() каждый раз, когда вы запускаете запрос, вы можете определить параметр как Class<T>, а затем передать вместо него Service.class.

person Davide    schedule 18.01.2018