JPA CriteriaBuilder: соединение списка с запросом при присоединении к cloumn

#java #spring #spring-data-jpa #criteria-api

#java #весна #spring-data-jpa #критерии-api

Вопрос:

У меня есть вариант использования, когда мне нужно выполнить поиск в таблице по списку значений. Ниже приведена схема:

Таблица обращений

Case_Id

Таблица CASE_CIN

Case_Id

cin

Таблица CASE и CASE_CIN объединяются через Многие ко многим.

Мне нужно искать обращения на основе предоставленного списка CIN. Это SQL, который я пытаюсь реализовать:

 select distinct c.* from case c left join case_cin cc on c.case_id = cc.case_id where cc.cin in ("cin1", "cin2", "cin3");
 

Вот как я разработал свои критерии фильтрации, основанные только на одном CIN:

 public static Specification<CaseEntity> buildSpecification(CaseSearchRequestDto criteria, String userName) {
    return (root, query, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
    
        if (!isEmpty(criteria.getAssociatePartyCins())) {
            predicates.add(buildAssociatePartyCinsFilterPredicate(root, cb, query, criteria.getAssociatePartyCins());
        }

        return cb.and(predicates.toArray(new Predicate[0]));
    };
}

private static Predicate buildAssociatePartyCinsFilterPredicate(Root<CaseEntity> root, CriteriaBuilder cb, CriteriaQuery query, List<String> cins) {
    Predicate filterPredicate = cb.disjunction();
    
    ListJoin<CaseEntity, String> cinsJoin = root.joinList(FIELD_CASE_CINS, LEFT);
    filterPredicate.getExpressions().add(startWithString(cinsJoin, cb, **cins.get(0)**); // need to change logic here.

    query.distinct(true);
    return filterPredicate;
}
 

Я также хотел бы иметь точное соответствие для каждого CIN, а не для этого startWithString .

Кто-нибудь может помочь изменить код, чтобы разрешить поиск по нескольким значениям?

Ответ №1:

Оказывается, это намного проще, чем я думал. Просто нужно заменить условие на cinsJoin.in(cins) .

 private static Predicate buildAssociatePartyCinsFilterPredicate(Root<CaseEntity> root, CriteriaBuilder cb, CriteriaQuery query, List<String> cins) {
    Predicate filterPredicate = cb.disjunction();
    
    ListJoin<CaseEntity, String> cinsJoin = root.joinList(FIELD_CASE_CINS, LEFT);
    filterPredicate.getExpressions().add(cinsJoin.in(cins));

    query.distinct(true);
    return filterPredicate;
}