Применить Spring-пейджинг к динамически создаваемому запросу - PullRequest
0 голосов
/ 13 марта 2019

Если у меня есть репозиторий Spring, я могу получить постраничные результаты, определив метод следующим образом (например):

@Query("<some JPAQL here>")
Page<Person> findBySomething(String foo, String bar, Pageable pageable);

Я бы хотел сделать то же самое, только для динамического создания запроса (сам запрос немного отличается в зависимости от некоторых входных данных). Что-то вроде:

String queryString = "<JPAQL part1>";
if (condition) queryString += "<JPAQL part2>";
queryString += "<JPAQL part3>";
Query query = entityManager.createQuery(queryString);
query.setParameter("foo", foo);
query.setParameter("bar", bar);
return query.getResultListAndApplySpringPaging(pageable);

Я не хочу переписать свой запрос в Querydsl или Criteria API. Частично потому, что я не хочу тратить на это время, а частично потому, что мой JPAQL содержит некоторые специфичные для Oracle вещи, которые может быть трудно, если не невозможно, выразить в них (например, такие вещи, как ORDER BY NLSSORT(t.displayValue, 'NLS_SORT = XCZECH') ASC).

Есть ли способ вручную передать String или javax.persistence.Query через механизм подкачки Spring?

Ответы [ 2 ]

0 голосов
/ 14 марта 2019

Итак, после некоторой отладки внутренних компонентов Spring у меня есть нечто, похожее на решение.Spring пропускает многое из того, что делает Spring (что означает, что он не такой общий), но, по крайней мере, для простых ситуаций он мне подходит.

String queryString = dynamicallyComposeQueryForConditions(someConditions);
String countQueryString = QueryUtils.createCountQueryFor(queryString);
Query query = entityManager.createQuery(queryString);
Query countQuery = entityManager.createQuery(countQueryString);
query.setParameter("foo", foo);
query.setParameter("bar", bar);
countQuery.setParameter("foo", foo);
countQuery.setParameter("bar", bar);
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
return PageableExecutionUtils.getPage(query.getResultList(), pageable,
        () -> (long) countQuery.getSingleResult());

Очевидно, что есть возможности для улучшения.Прежде всего, оба запроса должны иметь один и тот же набор параметров, что не должно быть сделано так, как я делаю это здесь по соображениям простоты.Во-вторых, getPage довольно умен, чтобы выполнить countQuery (или, точнее, totalSupplier), только если это необходимо (что не всегда).Это означает, что даже вызов QueryUtils.createCountQueryFor(queryString), а затем entityManager.createQuery(countQueryString) не всегда необходим и должен выполняться только внутри totalSupplier.

0 голосов
/ 14 марта 2019

Что делать, если вы создаете 2 метода: один с part2, другой без него, а затем вызываете правильный метод на основе условия.

@Query("<part part3>")
Page<Person> findBySomething(String foo, String bar, Pageable pageable);

@Query("<part1 part2 part3>")
Page<Person> findBySomethingElse(String foo, String bar, Pageable pageable);

...

return condition?findBySomethingElse(foo, bar, pageable):findBySomething(foo, bar, pageable);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...