2012-03-06 1 views
1

この問題を解決するのに手伝ってください。 私は2つのクラスを持っています。 1つはデバイス、2つ目はデバイスによって生成されたアラートです。 デバイスクラスは次のようになります。Hibernateは、一部の子プロパティによる検索時に常にeager loadingを使用しますか?

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を使用するSQLクエリを生成し、このアプローチには

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

crit.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE); 

問題は結果変圧器を適用し、その後、すべてのアラートを取得します。 それはこの

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を使用せずにアラートを持つすべてのデバイスを取得するにはどうすればよいですか? ORGでorg.hibernate.loader.criteria.CriteriaQueryTranslator.getProjectedTypesで java.lang.NullPointerExceptionが(CriteriaQueryTranslator.java:362) :

第二の例Iは、休止状態コードでNPEを午前のgettinを実施した後org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereConditionで.hibernate.criterion.SubqueryExpression.createAndSetInnerQuery org.hibernate.criterion.SubqueryExpression.toSqlString(SubqueryExpression.java:69)で(SubqueryExpression.java:153) (CriteriaQueryTranslator.java :380) at org.hibernate.loader.criteria.Cr iteriaJoinWalker。(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

答え1:あなたは、子プロパティでフィルタすると、SQLはする必要がありますchildtableに参加すると、関連ルートエンティティに

答え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>(); 
関連する問題