Spring Boot JPA: передача нескольких значений для одного и того же параметра (JPQL) - PullRequest
0 голосов
/ 12 января 2019

Я использую JPQL для написания SQL-запросов в интерфейсе JPA CurdRepository. Мне удалось написать более одного запроса с именованными параметрами, и они работают как шарм.

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

SELECT * FROM TABLE WHERE COLUMN_1 LIKE "%string_1%" OR COLUMN_1 LIKE"%string_2%" ... OR COLUMN_2 LIKE "%string_1%" OR COLUMN_2 LIKE "%string_2%" ... ...

Я пробовал это в MySQL, и он отлично работает. Однако я не мог понять, как изобразить это в JPQL. Я смог передать несколько значений для предложения IN, установив для именованного параметра значение List следующим образом:

 @Query("SELECT t FROM Table t WHERE TABLE_ID IN (:table_ids)")
public Page<Table> findByParameters(@Param("table_ids") List<Integer> table_ids, Pageable page)

Я пытался сделать то же самое с предложением LIKE, но я получаю 0 результатов, если я передал более 1 значения. Я сталкиваюсь с той же проблемой с предложением LOCATE.

В худшем случае я могу настроить один запрос, который работает с одной строкой, и вызвать его несколько раз, а затем объединить все результаты. Однако я бы предпочел этого избежать, так как это было бы не более чем решение для клейкой ленты.

Я часами искал решения в Интернете, но не нашел ничего, что отвечало бы моей проблеме. Любой совет высоко ценится.

Спасибо.

1 Ответ

0 голосов
/ 12 января 2019

Поскольку @Query необходимо исправить во время компиляции с использованием JPQL, или даже собственный запрос затруднит реализацию такого рода вещей, особенно безопасным способом.

Итак, я понимаю, что вам нужно решение JPQL, но это прекрасная возможность изучить и воспользоваться интерфейсом Specification и JPA CriteriaQuery. Это именно то, для чего.

Взгляните на следующий репозиторий:

public interface Table1Repository            // to use specifications in queries 
        extends JpaRepository<Table1, Long>, JpaSpecificationExecutor<Table1> {

    @SuppressWarnings("serial")
    public static Specification<Table1> multiLikeColumn1(List<String> likePatterns) {
        return new Specification<Table1>() {
            @Override
            public Predicate toPredicate(Root<Table1> root, CriteriaQuery<?> query,
                                            CriteriaBuilder criteriaBuilder) {
                Path<String> column1 = root.get("column1");
                // create a Predicate for each "column1 like 'xy%az%' you need
                List<Predicate> predicates = likePatterns.stream()
                    .map(likePattern -> criteriaBuilder.like(column1, likePattern))
                    .collect(Collectors.toList());
                // then "concatenate" list of likes with "OR"
                return criteriaBuilder.or(predicates.toArray(new Predicate[]{}));
            }
        };
    }

}

Это может показаться немного сложным, но на самом деле это не так, когда вы знакомитесь с ним. Использование просто, как:

@Resource
private Table1Repository repo;
repo.findAll(Table1Repository.multiLikeColumn1(Arrays.asList("%X%","%Z%")))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...