【问题标题】:Hibernate OGM with Mongodb Result of 2nd Query on same table dependent on Result fields of 1st query of same tableHibernate OGM 与 Mongodb 同一张表上的第二次查询结果取决于同一张表的第一次查询的结果字段
【发布时间】:2018-01-17 05:37:49
【问题描述】:

我正在使用 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;
    }

服务层:(问题:实验室名称: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 
    }
}

服务层:(临时解决方案)

 @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. 服务层:(问题:实验室名称:null)

这里我只使用第一次查询执行(变量名=查询)获取服务表的“名称”字段,然后执行第二次查询(变量名=另一个查询),但无法获取实验室对象。

  1. 服务层:(临时解决方案)

所以我使用第一个查询执行(变量名称 = 查询)获得了“名称”和“实验室 ID”这两个字段,然后我执行了第二个查询(变量名称 = anotherQuery),所以我不能成功获取实验室对象。

我不明白这一点。 即使查询不同且变量名也不同,第二个查询结果似乎取决于第一个查询结果字段。

我说的对吗?

【问题讨论】:

    标签: java spring hibernate hibernate-ogm


    【解决方案1】:

    使用本机查询,如果您选择在根类上应用投影,则必须删除 toEntity,因为不应允许部分实体提取。 很可能会在产品的下一个版本中引入异常抛出来防止这种使用。 这也是 Hibernate ORM (5.2 | 5.3) 在 H2 方言上的当前行为。

    【讨论】:

      【解决方案2】:

      编辑: 问题是第一个查询的结果被缓存(在会话级别),然后在第二个查询中重用。因为您运行的初始查询不会返回所有字段,所以实体只是部分初始化。当您想要重新创建实体时,请确保返回所有字段。当用户尝试重新创建仅具有属性子集的实体时,Hibernate OGM 应该引发异常。我将为此创建一个新的 JIRA。

      当您指定{name: 1} 时,您要求仅返回以下字段:_idname; 因为您要求提供服务,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&lt;T&gt;,然后传递Service.class来代替。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-25
        • 1970-01-01
        • 2015-03-16
        • 1970-01-01
        • 2018-11-25
        • 2014-08-17
        • 1970-01-01
        • 2022-10-07
        相关资源
        最近更新 更多