Hibernate在通过某些子属性进行搜索时是否总是使用即时加载?

Hibernate在通过某些子属性进行搜索时是否总是使用即时加载?,hibernate,lazy-loading,Hibernate,Lazy Loading,你能帮我解决这个问题吗。 我有两门课。一个是设备,第二个是设备生成的警报。 设备类看起来像 public class Device { private Long deviceId; private String deviceName; @OneToMany private List<Alert> alerts; } public class Alert { private Long deviceId; private Stri

你能帮我解决这个问题吗。 我有两门课。一个是设备,第二个是设备生成的警报。 设备类看起来像

public class Device
{
    private Long deviceId;  
    private String deviceName;
    @OneToMany
    private List<Alert> alerts;
}

public class Alert
{
    private Long deviceId;  
    private String alertText;
    private String alertType;
    private Date alertTime;
}
此方法的问题是,生成的SQL查询检索所有警报,然后应用结果转换器。 看起来像这样

select deviceID,deviceName,alertText,alertType,alertTime from devices d, alerts a left join  a.deviceID=d.deviceID;
这个查询效率不高。如果警报表很大,则需要几分钟的时间。 因此,我有一些问题:

  • 将添加
    alertCriteria.add(Resrictions.between(“alertTime”)、开始日期、结束日期)总是导致在一次选择中获取警报?如何避免呢
  • 在不使用ResultTransformer的情况下,如何使所有不同的设备都具有警报

在实现第二个示例后,我在hibernate代码中获得了NPE: java.lang.NullPointerException 位于org.hibernate.loader.CriteriaQueryTranslator.getProjectedTypes(CriteriaQueryTranslator.java:362) 位于org.hibernate.criteria.SubqueryExpression.createAndSetInnerQuery(SubqueryExpression.java:153) 位于org.hibernate.criteria.SubqueryExpression.toSqlString(SubqueryExpression.java:69) 位于org.hibernate.loader.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:380) 位于org.hibernate.loader.criteria.CriteriaJoinWalker(CriteriaJoinWalker.java:102) 位于org.hibernate.loader.criteria.CriteriaJoinWalker(CriteriaJoinWalker.java:82) 位于org.hibernate.loader.criteria.CriteriaLoader.(CriteriaLoader.java:92) 位于org.hibernate.impl.SessionImpl.list(SessionImpl.java:1697)
在org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:347)

回答1:当您按子属性筛选时,sql必须连接到子表以获取关联的根实体

回答2:如果您需要在给定范围内具有任何警报的设备

List<Device> devicesWithAlerts = session.createCriteria(Device.class, "device")
    .createCriteria("alerts")
        .add(Resrictions.between("alertTime", startDate, endDate))
    .setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE)
    .List<Device>();

// or more efficiently because only wanted entities are loaded

List<Device> devicesWithAlerts = session.createCriteria(Device.class, "device")
    .Add(Subqueries.PropertyIn("id", DetachedCriteria.For(Device.class)
        .CreateCriteria("alerts")
            .add(Resrictions.between("alertTime", startDate, endDate))
        .SetProjection(Projections.Distinct(Projections.Id()))
        ))
    .List<Device>();
List devicesWithAlerts=session.createCriteria(Device.class,“设备”)
.createCriteria(“警报”)
.add(Resrictions.between(“alertTime”、startDate、endDate))
.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE)
.List();
//或者更有效,因为只加载所需的实体
列出设备WithAlerts=session.createCriteria(Device.class,“设备”)
.Add(subquerys.PropertyIn(“id”),DetachedCriteria.For(Device.class)
.CreateCriteria(“警报”)
.add(Resrictions.between(“alertTime”、startDate、endDate))
.SetProjection(projects.Distinct(projects.Id()))
))
.List();
List<Device> devicesWithAlerts = session.createCriteria(Device.class, "device")
    .createCriteria("alerts")
        .add(Resrictions.between("alertTime", startDate, endDate))
    .setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE)
    .List<Device>();

// or more efficiently because only wanted entities are loaded

List<Device> devicesWithAlerts = session.createCriteria(Device.class, "device")
    .Add(Subqueries.PropertyIn("id", DetachedCriteria.For(Device.class)
        .CreateCriteria("alerts")
            .add(Resrictions.between("alertTime", startDate, endDate))
        .SetProjection(Projections.Distinct(Projections.Id()))
        ))
    .List<Device>();