JPA Criteria Builder OneToMany限制

时间:2015-03-19 13:30:34

标签: java jpa one-to-many

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

我试图用CriteriaBuilder编写一个查询来限制从Child表返回的结果。

我添加谓词,比如

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

如果父母有一个儿子或SON和女儿,它会回到那个父母,但也会归还他们所有的孩子。

Hibernate使用我的谓词触发第一个查询,但第二个查询以获取子节点只使用其不包含的where子句中的JoinColumn

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

思想?

我正在使用SetJoin

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

澄清:

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

3 个答案:

答案 0 :(得分:4)

我担心,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);

答案 1 :(得分:0)

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

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

而不是

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

答案 2 :(得分:0)

对于将来的引用,这来自另一篇帖子,对我(link)有所帮助: 代替parent.joinSet,使用fetch,然后将其强制加入:

output$tab1 <- renderTable({

    if (input$submit_kwic== 0){return()}      
    else{
      isolate({
        validate(
          need(input$word1 !='',"No table output shown as word 1 is not supplied"),
          need(sum(grepl(input$word1, x = attr(tokens_wo_stp, "types"))) >= 1,"Word does not exist in vocabulary, try another word!")
        )
        table1()
      })
    }}, striped = TRUE, hover = TRUE, bordered = TRUE)

正如上面链接中提到的那样,这不是完美的解决方案,但它为我省去了很多麻烦。