【问题标题】:How to check if entity in set contains a certain value using criteriaBuilder?如何使用criteriaBuilder检查集合中的实体是否包含某个值?
【发布时间】:2021-03-10 17:46:03
【问题描述】:

我有以下课程:

@Entity
public class Object {
   @ManyToOne
   @JoinColumn(name="RelationId", referencedColumnName = "ID", nullable=true)
   private Relation relation;
}

@Entity
public class Relation{
   @OneToMany(mappedBy="relation")
   private Set<Object> objects = new HashSet<>();

   @OneToMany(mappedBy="relation")
   private Set<Contact> contactpersons = new HashSet<>();
}

@Entity
public class Contact{
   @ManyToOne
   @JoinColumn(name="RelationId")
   private Relation relation;

   private Boolean isPrimary;
}

这是我的 rootQuery 的一些代码:

private Stream<Specification<Object>> toSpec(List<SearchCriteria> searchCriteria){
   return searchCriteria.stream().map(criteria ->{
        if (criteria.isSet(ObjectKeys.searchObject)) {
            return (Specification<Object>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
           
            [Here a criteriabuilder predicate needs to go that check if object has relation that has 
            contacts that have isPrimary on true]

           return criteriaBuilder.or(predicates.toArray(new Predicate[0]));
        }
    }
   }    
}

如何使用标准构建器检查对象的关系是否包含isPrimary 为 true 的联系人

我尝试使用criteriaBuilder.in(),但这只能检查联系人对象是否在集合中,而不能检查联系人对象是否具有特定值。我也尝试过使用连接,但这并没有给我正确的结果,因为我只能使用左、内或右连接,这会导致重复的对象或不可为空的对象。

【问题讨论】:

    标签: java hibernate jpa criteria criteria-api


    【解决方案1】:

    您在这里想要的是所谓的关系代数中的半连接,它通过 SQL 中的 EXISTS 谓词建模,并且在 JPA 中也支持。您必须使用带有存在谓词的相关子查询。大致如下:

    private Stream<Specification<Object>> toSpec(List<SearchCriteria> searchCriteria){
       return searchCriteria.stream().map(criteria ->{
            if (criteria.isSet(ObjectKeys.searchObject)) {
                return (Specification<Object>) (root, query, criteriaBuilder) -> {
                    Subquery<Integer> subquery = query.subquery(Integer.class);
                    Root<Object> correlated = subquery.correlate(root);
                    Join<?, ?> join = correlated.join("relation").join("contactpersons");
                    subquery.select(criteriaBuilder.literal(1));
                    subquery.where(criteriaBuilder.isTrue(join.get("isPrimary")));
                    return criteriaBuilder.exists(subquery);
                }
            }
       }    
    }
    

    【讨论】:

    • 这行得通!我真的找不到一个很好的例子,所以非常感谢!
    • 我确实将 Join,?> 更改为 Join, Contact> 但这只是一个小改动
    猜你喜欢
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多