JPA Criteria Builder一对多限制

hel*_*ity 4 java jpa one-to-many

我有一个父母与一个孩子表的OneToMany关联。

我正在尝试使用CriteriaBuilder编写查询,以限制从Child表返回的结果。

我要添加一个谓词,例如

cb.equal(parent.get("children").get("sex"), "MALE")
Run Code Online (Sandbox Code Playgroud)

如果父母有儿子或儿子和女儿,则是在返还该父母的同时还返还他们所有的孩子。

Hibernate使用我的谓词触发第一个查询,但是第二个获取子项的查询仅在不包含where子句的情况下使用JoinColumn

cb.equal(parent.get("children").get("sex"), "MALE").
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

我正在使用SetJoin

children = parent.joinSet("children", JoinType.LEFT)
Run Code Online (Sandbox Code Playgroud)

澄清:

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;
    };
}
Run Code Online (Sandbox Code Playgroud)

And*_*i I 5

恐怕,JOIN ON它不能按您期望的那样工作。JOIN ON仅告诉如何加入,而不告诉如何加载关系。

因此,为了解决您的问题,您将必须在加载子项后对其进行过滤,或者使用单独的查询手动获取所有男子项。

为了检查JOIN ON工作原理,您还可以尝试相应的JPQL查询。


更新

OP告知JPQL查询select p from parent p join fetch children c where p.parentId = :parentId and c.sex = "MALE"有效。

相应的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);
Run Code Online (Sandbox Code Playgroud)


Ant*_*sss 3

当您创建一个JOIN(特别是当属性是集合类型而不是 时SingularAttribute,您必须使用它来构建条件,因此使用

cb.equal(children.get("sex"), "MALE").
Run Code Online (Sandbox Code Playgroud)

代替

cb.equal(parent.get("children").get("sex"), "MALE").
Run Code Online (Sandbox Code Playgroud)