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);
总是会导致在一个选择中提取警报?怎么避免呢?实现第二个例子后,我在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)
答案 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>();