Hibernate OGM with Mongodb Result of 2nd Query on same table dependent on Result fields of 1st query of same table

我们两清 提交于 2019-12-11 15:27:02

问题


I am using Hibernate OGM (5.2.0.Alpha1) with 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....
}

Dao Layer:

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;
    }

Service Layer : (Issue : Lab name : null)

@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 
    }
}

Service Layer : (Temporary Solution)

 @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
        }
    }

Detail Explanation :

  1. Service Layer : (Issue : Lab name : null)

Here i only get 'name' field of service table using 1st query execution (variable name = query) and then executed 2nd query(variable name = anotherQuery) , but can not get lab object.

  1. Service Layer : (Temporary Solution)

so i get 'name' and 'lab_LAB_ID' both fields using 1st query execution (variable name = query) and then i executed 2nd query(variable name = anotherQuery) so not i can successfully get lab object.

I don't understand this. It seems like 2nd query result is dependent on 1st query result fields even if query is different and variable name is also different.

Is I am right?


回答1:


Using native queries, if you choose to apply a projection on the root class you have to remove toEntity, because partial a entity extraction should not be allowed. It is likely that an exception throwing will be introduced in the next versions of the product to prevent this use. This is the current behaviour of Hibernate ORM (5.2 | 5.3) on H2 dialect too.




回答2:


EDIT: The problem is that the results of the first queries are cached (at session level) and then reused in the second query. Because the initial query you run does not return all the fields, the entity is only partially initialized. Make sure to return all the fields when you want to re-create the entity. Hibernate OGM should throw an exception when a user try to recreate an entity with only a subset of the properties. I will create a new JIRA for this.

When you specify the {name: 1}, you are asking to return only the following fields: _id and name; Because you asked for a service, Hibernate OGM will convert those values to a Service class. The problem is that the result does not contain the lab and therefore that field is null (there should be an exception instead).

When you run db.service.find({} , {"name":1,"lab_LAB_ID":1}), you are also returning the Lab identifier, with this additional information OGM will be able to also add the lab to the service.

The native query you should use, if you want the whole service, is:

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

But I would recommend a HQL query for this scenario:

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

By the way, you don't need to create a new Service() every time you run the query, you can define the parameter as Class<T> and then pass Service.class instead.



来源:https://stackoverflow.com/questions/48294248/hibernate-ogm-with-mongodb-result-of-2nd-query-on-same-table-dependent-on-result

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!