JPA CriteriaBuilder查找具有集合中具有某些属性的元素的实体

时间:2016-04-19 14:44:29

标签: entity-framework jpa collections predicates

我有一个包含元素列表的实体,现在我想搜索这些元素的属性。这个约束应该是"和"连接的。请看这些简单的例子:

@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;

}    

现在我想在某个城市找到父母,让我们说&#34; BigCity&#34;和孩子一起上学&#34; AwesomeSchool&#34;这是在课堂/第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));

不幸的是,这里有两个问题: - 看起来我无法在list属性上调用get("school") - 这将归还所有有孩子的父母,这些孩子要么在#Aw ;; AwesomeSchool&#34;或者在学校6年。

你能帮帮我吗?我考虑过使用连接,但同样的问题是:如何定义连接的where部分,以便它认为必须同时满足两个属性(school和yearInSchool)。 我找到了关于查询孩子满足一个条件的对象的类似帖子 - 但是这里孩子们必须同时满足两个条件。

更新1 如果我使用联接断言,例如&#34;学校&#34;一个孩子,我到目前为止关于谓词:

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

如何重用此连接对象断言也适用于第二个过滤条件?

1 个答案:

答案 0 :(得分:3)

您需要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