在某些子项属性搜索时,Hibernate是否始终使用急切加载?

时间:2012-03-06 19:31:32

标签: hibernate lazy-loading

你能帮我解决这个问题吗? 我有2节课。一个是Device,第二个是设备生成的Alert。 设备类看起来像。

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

然后我想让所有设备生成警报。为此,我使用Criteria.API

Criteria crit= session.createCriteria(Device.class);
Criteria alertCriteria=crit.createCreateria("alerts");
alertCriteria.add(Resrictions.between("alertTime", startDate, endDate));

crit.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE);

生成SQL查询的此方法出现问题,然后检索所有警报,然后应用结果转换器。 它看起来像这样

select deviceID,deviceName,alertText,alertType,alertTime from devices d, alerts a left join  a.deviceID=d.deviceID;

此查询效率不高。如果警报表很大,则需要几分钟。 因此我有一些问题:

  • 将添加alertCriteria.add(Resrictions.between("alertTime"),startDate,endDate);总是会导致在一个选择中提取警报?怎么避免呢?
  • 如何在不使用ResultTransformer的情况下让所有不同的设备都有警报?

实现第二个例子后,我在hibernate代码中获取NPE: 显示java.lang.NullPointerException     在org.hibernate.loader.criteria.CriteriaQueryTranslator.getProjectedTypes(CriteriaQueryTranslator.java:362)     在org.hibernate.criterion.SubqueryExpression.createAndSetInnerQuery(SubqueryExpression.java:153)     在org.hibernate.criterion.SubqueryExpression.toSqlString(SubqueryExpression.java:69)     在org.hibernate.loader.criteria.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 个答案:

答案 0 :(得分:0)

回答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>();