2016-04-19 48 views
0

我有一個包含元素列表的實體,現在我想搜索這些元素的屬性。這個約束應該是「和」連接的。請看看這些簡單的例子:JPA CriteriaBuilder找到具有集合中某些屬性元素的實體

@Entity 
public class Parent { 

    @Column 
    @Enumerated(EnumType.STRING) 
    private City city; 

    @OneToMany(...) 
    private List<Children> childrens; 
} 

@Entity 
public class Children { 

    @Column 
    @Enumerated(EnumType.STRING) 
    private School school; 

    @Column 
    private Integer yearInSchool; 

}  

現在我想找到父母在某個城市,可以說「BigCity」帶着孩子在學校「AwesomeSchool」,這是在課堂上/年6.我想要得到的搜索結果只能通過CriteriaBuilder。

到目前爲止我:

final CriteriaBuilder c = getCriteriaBuilder(); 
final CriteriaQuery<Parent> query = c.createQuery(Parent.class); 
final Root<Parent> r = query.from(Parent.class); 
query.select(r) 
     .where(c.and(c.equal(r.get("city"), City.BigCity)), 
       c.equal(r.get("childrens").get("school"), School.AwesomeSchool), 
       c.equal(r.get("childrens").get("yearInSchool"), 6)); 

遺憾的是這裏有兩個問題: - 它看起來像我不能在列表屬性 調用get("school") - 這將返回所有家長帶孩子它們要麼在「AwesomeSchool」或在學校6年。

你能幫助我嗎?我想過使用連接,但是同樣的問題是:如何定義連接的where部分,以便它認爲兩個屬性(school和yearInSchool)必須同時實現。 我發現了類似的帖子,關於查詢誰的孩子滿足一個條件的對象 - 但在這裏,孩子們必須同時滿足兩個條件。

更新1 如果我使用連接斷言例如在一個孩子的「學校」,我得到迄今關於謂語:

Predicate predicate = r.join("childrens").get("school").in(School.AwesomeSchool) 

如何重新加入這個對象斷言也是第二過濾條件?

+0

因爲你擁有它現在你會滿足於在一個時間孩子一個條件,讓孩子1可滿足一個條件,但孩子2的另一條件。你希望同一個孩子同時滿足這兩個條件,因此需要使用聯接並在第二個和第三個where子句中使用聯合對象。在執行Criteria部分之前,應將其寫爲普通的JPQL。 –

+0

嗨尼爾,謝謝你的評論。是的,你完全有我的問題。我更新了一個條件的聯合問題。我怎樣才能重用這個對象來篩選第二個條件? –

回答

1

您需要JOIN,然後使用JOIN對象在形成WHERE子句時形成連接。

Join childrenJoin = r.join("childrens"); 

query.where(c.and(c.equal(r.get("city"), City.BigCity)), 
       c.equal(childrenJoin.get("school"), School.AwesomeSchool), 
       c.equal(childrenJoin.get("yearInSchool"), 6)); 

也許你的意思是你JPQL是:

SELECT p FROM Parent p JOIN p.childrens c 
WHERE p.city = :theCity AND c.school = :theSchool AND c.yearInSchool = 6 
+0

謝謝。我會試試這個。但是當我讀到這篇文章時,如果這位家長有兩個孩子,一個在「AwesomeSchool」和10班,另一個在「SomeotherSchool」和6班,這是否也會返回父母「P」?因爲如果我看着父母,條件就滿足了:家長P在AwesomeSchool中有一個孩子,並且在6歲時有一個孩子。 –

相關問題