springframework query pagingandsortingrepository pagerequest pageable org example data custom pagination spring-data-jpa

pagination - query - Paginación JPA de Spring Data(paginable) con consultas dinámicas



spring data pageable custom query (4)

Tengo una consulta simple de la siguiente manera "select * from USERS". También uso Pageable para habilitar la paginación.

Esta consulta puede tener predicados opcionales basados ​​en los parámetros dados que son nulos o no.

Por ejemplo, si el parámetro "código" está dado y no es nulo, entonces la consulta se convierte en "seleccionar * de USUARIOS donde código =: código";

Por lo que sé, no puedo implementar esto usando la anotación @Query. Puedo implementar un repositorio personalizado y usar EntityManager para crear una consulta dinámica. Sin embargo, no estoy seguro de cómo puedo integrar "en página" con eso para recuperar los resultados paginados.

¿Cómo puedo conseguir esto?


Esto es muy fácil de hacer en Spring Data usando QueryDSL (como alternativa a la API de criterios). Se admite fuera de la caja con el siguiente método de QueryDSLPredicateExecutor donde puede pasar nulo como Predicado si no se aplican restricciones:

Page<T> findAll(com.mysema.query.types.Predicate predicate, Pageable pageable)

El uso de QueryDSL puede no ser una opción para usted; sin embargo, si mira la siguiente serie de tutoriales, es posible que obtenga algunas ideas.

http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-nine-conclusions/

La situación que tiene es realmente discutida por el autor en los comentarios a la parte 9 de su guía.


Obtener resultados de página para consultas querydsl es de alguna manera complicado ya que necesita dos consultas: una para el número total de entradas y otra para la lista de entradas que necesita en la página. Podría usar la siguiente superclase:

public class QueryDslSupport<E, Q extends EntityPathBase<E>> extends QueryDslRepositorySupport { public QueryDslSupport(Class<E> clazz) { super(clazz); } protected Page<E> readPage(JPAQuery query, Q qEntity, Pageable pageable) { if (pageable == null) { return readPage(query, qEntity, new QPageRequest(0, Integer.MAX_VALUE)); } long total = query.clone(super.getEntityManager()).count(); // need to clone to have a second query, otherwise all items would be in the list JPQLQuery pagedQuery = getQuerydsl().applyPagination(pageable, query); List<E> content = total > pageable.getOffset() ? pagedQuery.list(qEntity) : Collections.<E> emptyList(); return new PageImpl<>(content, pageable, total); } }


La información aquí es obsoleta. Haga que su repositorio implemente QueryDslPredicateExecutor y que la paginación sea gratuita.


Tienes que usar querydsl y construir tu where dependiendo de un parámetro no nulo, por ejemplo

BooleanBuilder where = new BooleanBuilder(); ... if(code != null){ where.and(YOURENTITY.code.eq(code)); }

y luego de ejecutar la consulta

JPAQuery query = new JPAQuery(entityManager).from(..) .leftJoin( .. ) ... .where(where)

y usa tu propia página

MaPage<YOURENTITY> page = new MaPage<YOURENTITY>(); page.number = pageNumber+1; page.content = query.offset(pageNumber*pageSize).limit(pageSize).list(...); page.totalResult = query.count();

Creo MyPage así

public class MaPage<T> { public List<T> content; public int number; public Long totalResult; public Long totalPages; ... }

funciona, pero si en su consulta tiene una búsqueda, tendrá esta advertencia

nov. 21, 2014 6:48:54 AM org.hibernate.hql.internal.ast.QueryTranslatorImpl list
WARN: HHH000104: firstResult / maxResults especificado con la obtención de recopilación; aplicando en la memoria!

y ralentizará su solicitud. Por lo tanto, la solución es obtener un paseo de la búsqueda y definir un @BatchSize(size=10) y usar Hibernate.initialize(....) para obtener datos en colecciones y otro tipo de objeto.

Muestra datos de entidades relacionadas para evitar la excepción de inicialización diferida con la configuración @BatchSize

Cómo ejecutar un JPAQuery con paginación usando Spring Data y QueryDSL