pageable page example custom and spring jpa pagination spring-data paging

example - spring boot custom pageable



Paginación en Spring Data JPA(límite y desplazamiento) (4)

Quiero que el usuario pueda especificar el límite (el tamaño de la cantidad devuelta) y el desplazamiento (el primer registro devuelto / índice devuelto) en mi método de consulta.

Aquí están mis clases sin ninguna capacidad de búsqueda. Mi entidad:

@Entity public Employee { @Id @GeneratedValue(strategy=GenerationType.AUTO) private int id; @Column(name="NAME") private String name; //getters and setters }

Mi repositorio

public interface EmployeeRepository extends JpaRepository<Employee, Integer> { @Query("SELECT e FROM Employee e WHERE e.name LIKE :name ORDER BY e.id") public List<Employee> findByName(@Param("name") String name); }

Mi interfaz de servicio:

public interface EmployeeService { public List<Employee> findByName(String name); }

Mi implementación de servicio:

public class EmployeeServiceImpl { @Resource EmployeeRepository repository; @Override public List<Employee> findByName(String name) { return repository.findByName(name); } }

Ahora aquí está mi intento de proporcionar capacidades de paginación que admitan desplazamiento y límite. Mi clase de entidad sigue siendo la misma.

Mi "nuevo" repositorio toma un parámetro paginable:

public interface EmployeeRepository extends JpaRepository<Employee, Integer> { @Query("SELECT e FROM Employee e WHERE e.name LIKE :name ORDER BY e.id") public List<Employee> findByName(@Param("name") String name, Pageable pageable); }

Mi "nueva" interfaz de servicio tiene dos parámetros adicionales:

public interface EmployeeService { public List<Employee> findByName(String name, int offset, int limit); }

Mi "nueva" implementación de servicio:

public class EmployeeServiceImpl { @Resource EmployeeRepository repository; @Override public List<Employee> findByName(String name, int offset, int limit) { return repository.findByName(name, new PageRequest(offset, limit); } }

Esto sin embargo no es lo que quiero. PageRequest especifica la página y el tamaño (número de página y tamaño de la página). Ahora, especificando el tamaño es exactamente lo que quiero, sin embargo, no quiero especificar la página de inicio #, quiero que el usuario pueda especificar el registro / índice inicial. Quiero algo similar a

public List<Employee> findByName(String name, int offset, int limit) { TypedQuery<Employee> query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.name LIKE :name ORDER BY e.id", Employee.class); query.setFirstResult(offset); query.setMaxResults(limit); return query.getResultList(); }

Específicamente los métodos setFirstResult () y setMaxResult (). Pero no puedo usar este método porque quiero usar la interfaz del repositorio del empleado. (¿O es realmente mejor definir consultas a través del entityManager?) De todos modos, ¿hay alguna manera de especificar el desplazamiento sin usar el entityManager? ¡Gracias por adelantado!


Tal vez la respuesta es un poco tarde, pero pensé en lo mismo. Calcule la página actual según el desplazamiento y el límite. Bueno, no es exactamente lo mismo porque "asume" que el desplazamiento es un múltiplo del límite, pero tal vez su aplicación sea adecuada para esto.

@Override public List<Employee> findByName(String name, int offset, int limit) { // limit != 0 ;) int page = offset / limit; return repository.findByName(name, new PageRequest(page, limit); }

Sugeriría un cambio de la arquitectura. Cambie su controlador o lo que sea que llame al servicio para darle inicialmente la página y el límite si es posible.


Probablemente no pueda hacerlo con datos de primavera jpa. Si el desplazamiento es muy pequeño, puede eliminar las declaraciones X superiores de la consulta después de la recuperación.

De lo contrario, podría definir el tamaño de página como el desplazamiento y comenzar en la página + 1.


Puedes hacer eso creando tu propio paginable.

Pruebe esta muestra básica. Funciona bien para mí:

public class ChunkRequest implements Pageable { private int limit = 0; private int offset = 0; public ChunkRequest(int skip, int offset) { if (skip < 0) throw new IllegalArgumentException("Skip must not be less than zero!"); if (offset < 0) throw new IllegalArgumentException("Offset must not be less than zero!"); this.limit = offset; this.offset = skip; } @Override public int getPageNumber() { return 0; } @Override public int getPageSize() { return limit; } @Override public int getOffset() { return offset; } @Override public Sort getSort() { return null; } @Override public Pageable next() { return null; } @Override public Pageable previousOrFirst() { return this; } @Override public Pageable first() { return this; } @Override public boolean hasPrevious() { return false; } }


Debajo del código debería hacerlo. Estoy usando mi propio proyecto y probado en la mayoría de los casos.

uso:

Pageable pageable = new OffsetBasedPageRequest(offset, limit); return this.dataServices.findAllInclusive(pageable);

y el código fuente:

import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.springframework.data.domain.AbstractPageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import java.io.Serializable; /** * Created by Ergin **/ public class OffsetBasedPageRequest implements Pageable, Serializable { private static final long serialVersionUID = -25822477129613575L; private int limit; private int offset; private final Sort sort; /** * Creates a new {@link OffsetBasedPageRequest} with sort parameters applied. * * @param offset zero-based offset. * @param limit the size of the elements to be returned. * @param sort can be {@literal null}. */ public OffsetBasedPageRequest(int offset, int limit, Sort sort) { if (offset < 0) { throw new IllegalArgumentException("Offset index must not be less than zero!"); } if (limit < 1) { throw new IllegalArgumentException("Limit must not be less than one!"); } this.limit = limit; this.offset = offset; this.sort = sort; } /** * Creates a new {@link OffsetBasedPageRequest} with sort parameters applied. * * @param offset zero-based offset. * @param limit the size of the elements to be returned. * @param direction the direction of the {@link Sort} to be specified, can be {@literal null}. * @param properties the properties to sort by, must not be {@literal null} or empty. */ public OffsetBasedPageRequest(int offset, int limit, Sort.Direction direction, String... properties) { this(offset, limit, new Sort(direction, properties)); } /** * Creates a new {@link OffsetBasedPageRequest} with sort parameters applied. * * @param offset zero-based offset. * @param limit the size of the elements to be returned. */ public OffsetBasedPageRequest(int offset, int limit) { this(offset, limit, new Sort(Sort.Direction.ASC,"id")); } @Override public int getPageNumber() { return offset / limit; } @Override public int getPageSize() { return limit; } @Override public int getOffset() { return offset; } @Override public Sort getSort() { return sort; } @Override public Pageable next() { return new OffsetBasedPageRequest(getOffset() + getPageSize(), getPageSize(), getSort()); } public OffsetBasedPageRequest previous() { return hasPrevious() ? new OffsetBasedPageRequest(getOffset() - getPageSize(), getPageSize(), getSort()) : this; } @Override public Pageable previousOrFirst() { return hasPrevious() ? previous() : first(); } @Override public Pageable first() { return new OffsetBasedPageRequest(0, getPageSize(), getSort()); } @Override public boolean hasPrevious() { return offset > limit; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof OffsetBasedPageRequest)) return false; OffsetBasedPageRequest that = (OffsetBasedPageRequest) o; return new EqualsBuilder() .append(limit, that.limit) .append(offset, that.offset) .append(sort, that.sort) .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder(17, 37) .append(limit) .append(offset) .append(sort) .toHashCode(); } @Override public String toString() { return new ToStringBuilder(this) .append("limit", limit) .append("offset", offset) .append("sort", sort) .toString(); } }