2014-01-09 59 views
1

我有兩個具有一對多關係的實體對象(A和B)。我正在使用JPA(Hibernate)來連接這些表並查詢它們以獲取特定的結果集,但是在獲取我的結果時不會應用我爲子表(B)指定的條件。這就是我所定義的查詢:在一對多關係中指定子表的標準

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<A> query = builder.createQuery(A.class); 
Root<A> a = query.from(A.class); 
Join<A, B> abJoined = a.join(A_.b); 

query.distinct(true) 
    .where(builder.and(
     builder.equal(a.get(A_.id), id), 
     builder.equal(a.get(A_.active), 1), 
     builder.equal(a.get(A_.location), 1011), 
     builder.equal(a.get(A_.status), "Pending"), 

     builder.equal(abJoined.get(B_.status), "Not Moved"), 
     builder.greaterThan(abJoined.get(B_.detailId), 0) 
    )); 

當我打電話entityManager.createQuery(query).getResultList();我得到實體的「A」一個實例,但是當我試圖通過「A」 a.getB()兩個標準,我不得不進入「B」指定爲abJoined未應用,並且我獲得了連接到'A'的'B'的所有實例。我還需要做些什麼來獲得這些標準?如果標準不能應用,是否有推薦的方法從結果集中去除相應的'B'實例?

我可以根據需要提供更多代碼或其他細節。

回答

0

該查詢用於選擇查詢必須返回哪個實體。但是A實體永遠不會是僅包含其子集的子集的部分實體。它們將始終是A的完整實例,反映A在數據庫中的狀態以及與A有關的B。

順便說一句,即使這是可能的(它不是,並明確禁止JPA規範),您的查詢至少也必須加載Bs以及使用fetch連接。否則,只有查詢返回A的狀態,並且鏈接的Bs會被延遲加載。

+0

這是有道理的,我認爲這可能是問題。是否有推薦的方法去除結果集中不需要的'B'實例? – Christopher

+0

使用查詢選擇它們,並使用ManyToTone關聯反轉來獲取它們的A. –

0

但是在JPA中,對於@OneToMany關係,首先在主服務器上觸發Query,並使用所有Criteria並僅提取主記錄。 後來逐個查詢被觸發,但是但是...... B表標準將不包含所有條件,但只有一個條件,即只是主記錄的主鍵VALUE,即只有一個條件「b .A_id = [從主primarykeyfetched]」

溶液簡單 作出獨立類,在此我們需要的@OneToMany關係領域

STEP 1

public class AB { 

    private A a; 
    private B b; //@OneToMany with A in the Entity class definitions 

public AB(){} 

public AB(A a, B b){ ///Very Important to have this constructor 
    this.a=a; 
    this.b=b; 
} 

getter setter.... 

} 

STEP 2

CriteriaQuery<AB> q = criteriaBuilder.createQuery(AB.class); 
Root<A> fromA = criteriaQuery.from(A.class);  
List<Predicate> predicates = new ArrayList<Predicate>();   
Join<A,B> fromB = fromA.join("b", JoinType.INNER);/*"b",fieldName of B in entity Class A*/ 
criteriaQuery.select(criteriaBuilder.construct(AB.class,A,B));//looks AB's 2 param constr. 
predicates.add(criteriaBuilder.equal(fromA.get("name"), filter.getName())); 
predicates.add(criteriaBuilder.equal(fromB.get("salary"), filter.getSalary())); 
.......... 
List<AB> ABDataList = typedQuery.getResultList(); 
for(AB eachABData :ABDataList){ 
    ....put in ur objects 
    obj.setXXX(eachABData.getA().getXXX()); 
    obj.setYYY(eachABData.getB().getYYY()); 
} 

這將給所有的結果應用所有的標準來掌握表A,並比較表B的主鍵而不是外鍵。

相關問題