Spring Data JPA의 페이지 번호(한계 및 오프셋
사용자가 내 쿼리 방법에서 제한(반환된 양의 크기)과 오프셋(반환된 첫 번째 레코드/인덱스)을 지정할 수 있기를 원합니다.
호출 기능이 없는 수업입니다.내 실체:
@Entity
public Employee {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="NAME")
private String name;
//getters and setters
}
내 리포지토리:
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);
}
내 서비스 인터페이스:
public interface EmployeeService {
public List<Employee> findByName(String name);
}
내 서비스 구현:
public class EmployeeServiceImpl {
@Resource
EmployeeRepository repository;
@Override
public List<Employee> findByName(String name) {
return repository.findByName(name);
}
}
이제 오프셋과 제한을 지원하는 페이징 기능을 제공하려는 시도가 있습니다.엔티티 클래스가 그대로 유지됩니다.
내 "새" 리포지토리는 페이지 가능한 매개 변수를 사용합니다.
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);
}
"새로운" 서비스 인터페이스에는 다음과 같은 두 가지 추가 매개 변수가 추가됩니다.
public interface EmployeeService {
public List<Employee> findByName(String name, int offset, int limit);
}
"새로운" 서비스 구현:
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);
}
}
하지만 이것은 제가 원하는 것이 아닙니다.페이지 요청은 페이지 및 크기(페이지 번호 및 페이지 크기)를 지정합니다.이제 크기를 지정하는 것이 정확히 제가 원하는 것입니다. 하지만 시작 페이지 번호를 지정하고 싶지 않습니다. 사용자가 시작 레코드/인덱스를 지정할 수 있기를 바랍니다.저는 비슷한 것을 원합니다.
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();
}
구체적으로 setFirstResult() 및 setMaxResult() 메서드입니다.하지만 Employee repository 인터페이스를 사용하고 싶어서 이 메서드를 사용할 수 없습니다. (아니면 entityManager를 통해 쿼리를 정의하는 것이 더 나은가요?)
entityManager를 사용하지 않고 오프셋을 지정할 수 있는 방법이 있습니까?
아래의 코드가 그것을 할 것입니다.저는 제 프로젝트에서 사용하고 있으며 대부분의 경우 테스트를 거쳤습니다.
용도:
Pageable pageable = new OffsetBasedPageRequest(offset, limit);
return this.dataServices.findAllInclusive(pageable);
소스 코드:
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, Sort.unsorted());
}
@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();
}
}
사용자 자신의 페이지 테이블을 작성하여 이 작업을 수행할 수 있습니다.
이 기본 샘플을 사용해 보세요.잘 작동합니다.
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
public class ChunkRequest implements Pageable {
private final int offset;
private final int limit;
// this attribute can be let out if you don't need it
private Sort sort;
public ChunkRequest(int offset, int limit, Sort sort) {
if (offset < 0)
throw new IllegalArgumentException("Offset must not be less than zero!");
if (limit < 0)
throw new IllegalArgumentException("Limit must not be less than zero!");
this.offset = offset;
this.limit = limit;
if (sort != null) {
this.sort = sort;
}
}
public ChunkRequest(int offset, int limit) {
this(offset, limit, null);
}
@Override
public int getPageNumber() { return 0; }
@Override
public int getPageSize() { return limit; }
@Override
public long getOffset() { return offset; }
@Override
public Sort getSort() { return this.sort; }
@Override
public Pageable next() { return null; }
@Override
public Pageable previousOrFirst() { return this; }
@Override
public Pageable first() { return this; }
@Override
public Pageable withPage(int pageNumber) { return null; }
@Override
public boolean hasPrevious() { return false; }
}
여기 있습니다.
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
@Query(value="SELECT e FROM Employee e WHERE e.name LIKE ?1 ORDER BY e.id offset ?2 limit ?3", nativeQuery = true)
public List<Employee> findByNameAndMore(String name, int offset, int limit);
}
답이 좀 늦었을 수도 있지만, 저도 같은 생각을 했습니다.오프셋 및 한계를 기준으로 현재 페이지를 계산합니다.오프셋이 한계의 배수라고 "가정"하기 때문에 정확히 같지는 않지만, 응용 프로그램이 이에 적합할 수 있습니다.
@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));
}
저는 건축의 변화를 제안하고 싶습니다.컨트롤러 또는 서비스 호출을 변경하여 처음에 페이지를 제공하고 가능한 경우 제한합니다.
긴 오프셋과 Sort.by 을 사용한 good @httpmonkey 오너 적용.
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.Pageable;
import org.springframework.data.domain.Sort;
import java.io.Serializable;
public class OffsetBasedPageRequest implements Pageable, Serializable {
private static final long serialVersionUID = -25822477129613575L;
private final int limit;
private final long 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(long 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(long offset, int limit, Sort.Direction direction, String... properties) {
this(offset, limit, Sort.by(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, Sort.unsorted());
}
@Override
public int getPageNumber() {
return Math.toIntExact(offset / limit);
}
@Override
public int getPageSize() {
return limit;
}
@Override
public long 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();
}
}
스프링 데이터 jpa로는 아마 이것을 할 수 없을 것입니다.오프셋이 매우 작으면 검색 후 쿼리에서 상위 X 문을 제거할 수 있습니다.
그렇지 않으면 페이지 크기를 오프셋으로 정의하고 +1페이지에서 시작할 수 있습니다.
시도:
public interface ContactRepository extends JpaRepository<Contact, Long>
{
@Query(value = "Select c.* from contacts c where c.username is not null order by c.id asc limit ?1, ?2 ", nativeQuery = true)
List<Contact> findContacts(int offset, int limit);
}
필터링 및 정렬과 페이징을 동시에 수행한다고 가정합니다. 아래 @Query가 도움이 됩니다.
@Query(value = "SELECT * FROM table WHERE firstname= ?1 or lastname= ?2 or age= ?3 or city= ?4 or "
+ " ORDER BY date DESC OFFSET ?8 ROWS FETCH NEXT ?9 ROWS ONLY" , nativeQuery = true)
List<JobVacancy> filterJobVacancyByParams(final String firstname, final String lastname,
final String age, final float city,int offset, int limit);
언급URL : https://stackoverflow.com/questions/25008472/pagination-in-spring-data-jpa-limit-and-offset
'sourcecode' 카테고리의 다른 글
MySQL을 사용하여 '주요'에 대한 'KEY' 항목이 중복됨 (0) | 2023.08.31 |
---|---|
PowerShell 프롬프트에 유니코드 문자 인쇄 (0) | 2023.08.31 |
SQL 쿼리의 표준 시간대 변환 (0) | 2023.08.31 |
C#의 Dapper와 Heidi의 Stored Procedure를 사용하면 null 값을 얻습니다. (0) | 2023.08.31 |
스칼라와 마리아를 이용한 간단한 curd rest api (0) | 2023.08.31 |