简体   繁体   English

JPA Criteria Builder OneToMany限制

[英]JPA Criteria Builder OneToMany Restrictions

I have a Parent with a OneToMany associations with a Child Table. 我有一个父子与OneToMany关联与子表。

I'm trying to write a query with CriteriaBuilder to restrict the results returned from the Child table. 我正在尝试使用CriteriaBuilder编写查询来限制从Child表返回的结果。

I'm adding a Predicate, something like 我正在添加谓词,类似于

cb.equal(parent.get("children").get("sex"), "MALE")

If the Parent has a son or SON and Daughter it's returning that parent but also returning all the children they have. 如果父母有一个儿子或者SON和女儿它正在返回那个父母,但也返回他们拥有的所有孩子。

Hibernate fires off the first query with my predicates but the second query to get the children only uses the JoinColumn in the where clause it doesn't include Hibernate使用我的谓词触发第一个查询,但第二个查询以获取子节点仅使用where子句中不包含的JoinColumn

cb.equal(parent.get("children").get("sex"), "MALE").

Thoughts? 思考?

I am using a SetJoin 我正在使用SetJoin

children = parent.joinSet("children", JoinType.LEFT)

CLARIFICATION: 澄清:

public static Specification<Parent> findPlanBenefits(Integer parentId) {
    return (parent, query, cb) -> {
        Predicate predicates = cb.conjunction();
        List<Expression<Boolean>> expressions = predicates.getExpressions();

        //Parent Criteria
        expressions.add(cb.equal(parent.get("parentId"), parentId));

        //Children Criteria
        SetJoin<Parent, Children> children = parent.joinSet("children", JoinType.LEFT);

        Predicate sex = cb.equal(children.get("sex"), "MALE");
        children.on(sex);

        return predicates;
    };
}

I am afraid, the JOIN ON does not work as you expect in your answer. 我担心, JOIN ON在你的答案中没有像你期望的那样工作。 JOIN ON only tells how to join, and NOT how relationships are loaded. JOIN ON仅告知如何加入,而不是如何加载关系。

So, in order to solve your problem you will have to filter the children after they are loaded, or fetch manually all male children with a separate query. 因此,为了解决您的问题,您必须在加载后过滤子项,或者使用单独的查询手动获取所有男性子项。

In order to check how JOIN ON works, you could try also the corresponding JPQL query. 为了检查JOIN ON工作原理,您还可以尝试相应的JPQL查询。


UPDATE UPDATE

OP told that the JPQL query select p from parent p join fetch children c where p.parentId = :parentId and c.sex = "MALE" works. OP告诉JPQL查询select p from parent p join fetch children c where p.parentId = :parentId and c.sex = "MALE"有效。

The corresponding CriteriaQuery would look like: 相应的CriteriaQuery看起来像:

CriteriaQuery<Parent> criteria = cb.createQuery((Class<Parent>) Parent.class);
Root<Parent> parent = criteria.from(Parent.class);

criteria.select((Selection<T>) parent);
SetJoin<Parent, Children> children = parent.joinSet("children", JoinType.LEFT);

Predicate sexPredicate = cb.equal(children.get("sex"), "MALE");
parent.fetch(children);
//parent.fetch("children");//try also this

criteria.where(sexPredicate);

When you create a JOIN (especially when property is collection type, not SingularAttribute , you have to use it to build the criteria, so use 当您创建JOIN (特别是当属性是集合类型,而不是SingularAttribute ,您必须使用它来构建条件,因此使用

cb.equal(children.get("sex"), "MALE").

instead of 代替

cb.equal(parent.get("children").get("sex"), "MALE").

For the future referrence, this is from another post, that helped me (link) : Instead of parent.joinSet use fetch and then cast it to join: 对于未来的参考,这是来自另一篇文章,它帮助我(链接) :而不是parent.joinSet使用fetch然后将其转换为join:

Join<Parent, Children> join = (Join<Parent, Children>)parent.fetch(Parent_.children);

As mentioned in the post linked above it is not perfect solution but it saved me a lot of headaches. 正如上面链接的帖子中提到的那样,它并不是完美的解决方案,但它让我很烦恼。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM