【问题标题】:JPA CriteriaBuilder find entity which has elements with certain attributes in collectionJPA CriteriaBuilder 查找集合中具有某些属性的元素的实体
【发布时间】:2016-04-19 14:44:28
【问题描述】:

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

@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 部分,以便它认为必须同时满足两个属性(学校和 yearInSchool)。 我发现了有关查询其子项满足一个条件的对象的类似帖子 - 但这里的子项必须同时满足两个条件。

更新 1 如果我使用连接来断言,例如一个孩子的“学校”,我到目前为止关于谓词:

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

我怎样才能重用这个连接的对象来断言也适用于第二个过滤条件?

【问题讨论】:

  • 正如您目前拥有的那样,您将一次满足孩子的一个条件,因此孩子 1 可能满足一个条件,但孩子 2 可能满足另一个条件。您希望同一个孩子同时满足这两个条件,因此需要在第二个和第三个 where 子句中使用连接并使用连接对象。值得在做 Criteria 部分之前把它写成普通的 JPQL。
  • 嗨,尼尔,感谢您的评论。是的,你完全解决了我的问题。我用一个条件的连接更新了问题。我怎样才能重用这个对象来过滤第二个条件?

标签: entity-framework jpa collections predicates


【解决方案1】:

你需要JOIN,然后在形成WHERE子句时使用你在形成连接时得到的JOIN对象。

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

【讨论】:

  • 谢谢。我会试试这个。但是当我读到这篇文章时,如果这个父母有两个孩子,一个在“AwesomeSchool”和第 10 班,第二个在“SomeotherSchool”和第 6 班,这不会也返回一个父母“P”吗?因为如果我查看父母,则满足条件:父母 P 有一个在 AwesomeSchool 的孩子和一个在 6 年级的孩子。
猜你喜欢
  • 2023-03-18
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 2012-12-10
  • 1970-01-01
相关资源
最近更新 更多