2016-04-19 49 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岁时有一个孩子。 –

相关问题