동면 상태의 스프링 부츠에서 호출을 구현하는 방법
동면 상태에서 스프링부츠를 사용하고 있는데 프로젝트에서 페이지네이션을 사용하고 싶습니다.구글에서 검색해보니 많은 예시를 보았지만 프로젝트에서 구현할 수 없습니다.
제 url에 1을 통과하면 10개의 결과가 나오고 2를 통과하면 다음 10개의 결과가 나와야 하는 것과 같습니다.
여기 나의 Dao 입니다.
@Transactional
public interface PostDao extends CrudRepository<Post, Long>{
@Query(getAllPostsByRank)
List<Post> getAllPostsByRank();
final String getAllPostsByRank= "from Post order by value DESC";
}
여기 내 컨트롤러가 있습니다.
@RequestMapping("/top")
@ResponseBody
public List<Post> getAllPosts(HttpServletRequest req, HttpServletResponse res) throws ServletException {
List<Post> postobj = postDao.getAllPostsByRank();
return postobj;
}
여기 제 url이 있습니다.
http://localhost:8888/v1.0/post/top/1
제안 좀 해주세요.
사용을 고려해 보겠습니다.org.springframework.data.domain.Pageable
컨트롤러에 직접 연결할 수 있습니다.그러면 이 개체는 반환된 결과 수와 크기를 처리하는 JPA 계층으로 전달될 수 있습니다.
사용할 때의 좋은 점.Pageable
그것은 그것이 a를 반환한다는 것입니다.Page
이전/다음 페이지 로직을 형성하기 위해 프론트엔드에서 사용할 수 있는 object.
기본적으로 이 클래스는 URL 매개 변수 'page' 및 'size'를 사용하므로 page=0&size=10은 처음 10개의 항목을 반환합니다.
따라서 당신의 경우 코드는 다음과 같이 보일 수 있습니다.
@ResponseBody
@RequestMapping("/top/pages/")
public List<Post> getAllPosts(@PageableDefault(value=10, page=0) Pageable pageable) throws ServletException {
Page page = postDao.findAll(pageable);
return page.getContent();
}
주석을 주목합니다.@PageableDefault
기본값을 설정하는 것일 뿐이며 필요한 것은 아닙니다.
프론트엔드에서 다음 페이지 호출은<a href="/top/pages?page=1">Next</a>
; 그러면 게시물 목록이 11개에서 20개로 돌아갑니다.
Spring Boot에서 페이지 구성을 구현하는 것은 매우 쉬우며 기본적인 단계만 수행하면 됩니다.
1 - 저장소 인터페이스에서 PagingAndSortingRepository 확장
public interface UserRepository extends PagingAndSortingRepository <User, Long>
2 - Method Declaration은 아래 예제와 같아야 합니다.
Page<User> userList(Pageable pageable);
3 - 서비스 클래스에서의 방법 구현은 아래의 예와 같아야 합니다.
@Override
public Page<User> userList(Pageable pageable) {
return userRepository.findAll(pageable);
}
4 - 컨트롤러 클래스 코드는 아래와 같습니다.
@GetMapping("/list")
public String userList(Model model, Pageable pageable) {
Page<User> pages = userService.userList(pageable);
model.addAttribute("number", pages.getNumber());
model.addAttribute("totalPages", pages.getTotalPages());
model.addAttribute("totalElements",
pages.getTotalElements());
model.addAttribute("size", pages.getSize());
model.addAttribute("users", pages.getContent());
return "/user/list";
}
프론트엔드 통화는 아래와 같습니다.
http://localhost:8080/application/user/list?page=0&size=5
http://localhost:8080/application/user/list?page=1&size=5
http://localhost:8080/application/user/list?page=2&size=5
자세한 내용은 아래 동영상을 참조하십시오.
읽어주셔서 감사합니다.
확인해보세요.컨트롤러
@RequestMapping("/top/pages/{pageno}")
@ResponseBody
public List<Post> getAllPosts(@PathVariable("pageno") int pageno, HttpServletRequest req, HttpServletResponse res) throws ServletException {
List<Post> postobj = postDao.getAllPostsByRank(new PageRequest(pageno,10));
return postobj;
}
너의 dao
@Transactional
public interface PostDao extends CrudRepository<Post, Long>{
@Query(getAllPostsByRank)
List<Post> getAllPostsByRank(Pageable pageable);
final String getAllPostsByRank= "from Post order by value DESC";
}
저는 스프링부츠에 페이지네이션을 구현하였습니다.아래는 나의 Repository 입니다.
@Repository("userRepository")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
}
아래는 제 컨트롤러입니다.
@Controller
public class SampleController {
@Autowired
private UserRepository repository;
@GetMapping("/userview")
public String getEmployees(@PageableDefault(size = 1) Pageable pageable,
Model model) {
Page<User> page = repository.findAll(pageable);
model.addAttribute("page", page);
return "userdetail";
}
}
아래는 제가 타임리프를 사용했다는 것에 대한 견해입니다.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<h2>USER DETAILS</h2>
<table class="table table-striped table-responsive-md">
<thead>
<tr>
<th> ID </th>
<th>Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${page.content}">
<td th:text="${user.id}"></td>
<td th:text="${user.email}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.lastName}"></td>
<td th:text="${user.roles[0].role}"></td>
</tr>
</tbody>
</table>
<div class="pagination-div">
<span th:if="${page.hasPrevious()}">
<a th:href="@{/userview(page=${page.number-1},size=${page.size})}">Previous</a>
</span>
<th:block th:each="i: ${#numbers.sequence(0, page.totalPages - 1)}">
<span th:if="${page.number == i}" class="selected">[[${i}+1]]</span>
<span th:unless="${page.number == i}">
<a th:href="@{/userview(page=${i},size=${page.size})}">[[${i}+1]]</a>
</span>
</th:block>
<span th:if="${page.hasNext()}">
<a th:href="@{/userview(page=${page.number+1},size=${page.size})}">Next</a>
</span>
</div>
</body>
</html>
네이티브 쿼리를 이용한 동적 페이지화 구현 방법
여기서 저장소 및 서비스 계층과 데이터 전송 개체(DTO)를 찾을 수 있으며, 이 개체는 결과를 매핑하여 컨트롤러 계층으로 전송하는 데 사용됩니다.
public interface CustomSomethingRepository {
List<Something> findPagedResultBySomethingElseId(long somethingElseId, int offset, int limit);
}
public class SomethingRepositoryImpl implements CustomSomethingRepository {
@Autowired
private EntityManager em;
@SuppressWarnings("unchecked")
@Override
public List<Something> findPagedResultBySomethingElseId(long somethingElseId, int offset, int limit) {
String query = "select s.* from Something s "
+ "join somethingelse selse on selse.id = s.fk_somethingelse "
+ "where selse.id = :somethingElseId "
+ "order by selse.date";
Query nativeQuery = em.createNativeQuery(query);
nativeQuery.setParameter("somethingElseId", somethingElseId);
//Paginering
nativeQuery.setFirstResult(offset);
nativeQuery.setMaxResults(limit);
final List<Object[]> resultList = nativeQuery.getResultList();
List<Something> somethingList = Lists.newArrayList();
resultList.forEach(object -> somethingList.add(//map obj to something));
return somethingList;
}
}
Hibernate는 다음과 같이 쿼리를 변환합니다.
SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__ FROM ( select TOP(?) t as page0_ from Something s join s.somethingelse as selse order by selse.date ) inner_query ) SELECT page0_ FROM query WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?
@Service
public class SomethingService {
private SomethingRepository somethingRepository;
@Autowired
public SomethingService(SomethingRepository somethingRepository){
this.somethingRepository = somethingRepository;
}
@Transactional(readOnly=true)
public PageDto getSomething(long somethingElseId, int page, int size){
List<Something> somethings = somethingRepository.findBySomethingElseId(somethingElseId, offset, limit);
return new PagedResult<>(somethings
.stream()
.map(SomethingDto::createDto)
.sorted(comparing(SomethingDto::getDatum))
.collect(toList()), somethings.getTotalElements(), somethings.getTotalPages();
}
}
@Controller
//....
public class PagedResult<T> {
public static final long DEFAULT_OFFSET = 0;
public static final int DEFAULT_MAX_NO_OF_ROWS = 100;
private int offset;
private int limit;
private long totalElements;
private List<T> elements;
public PagedResult(List<T> elements, long totalElements, int offset, int limit) {
this.elements = elements;
this.totalElements = totalElements;
this.offset = offset;
this.limit = limit;
}
public boolean hasMore() {
return totalElements > offset + limit;
}
public boolean hasPrevious() {
return offset > 0 && totalElements > 0;
}
public long getTotalElements() {
return totalElements;
}
public int getOffset() {
return offset;
}
public int getLimit() {
return limit;
}
public List<T> getElements() {
return elements;
}
}
장단점:Spring Data를 사용하는 경우에 비해 SQL 쿼리가 더 적게 생성됩니다.이러한 복잡한 쿼리는 Spring Data에서 작성할 수 없으며 쿼리를 네이티브 쿼리로 지정해야 하며 이 방법론을 사용하여 호출할 수도 있습니다.
단점: "객체" 배열은 자바 객체에 매핑되어야 합니다.그것은 고통스럽고 유지하기 어렵습니다.
Spring Data로 OffsetLimit Pagination을 구현하는 방법 기본 Spring Data 저장소에서 필요한 것에 대한 "즉시" 지원은 없는 것으로 알고 있습니다.그러나 제한/오프셋 매개변수를 사용할 Pageable 개체의 사용자 지정 구현을 만들 수 있습니다.
페이지가 가능한 개체를 만들어 PaginationAndSortingRepository:
public class OffsetLimitRequest implements Pageable {
private int limit;
private int offset;
public OffsetLimitRequest(int offset, int limit){
this.limit = limit;
this.offset = offset;
}
@Override
public int getPageNumber() {
return 0;
}
@Override
public int getPageSize() {
return limit;
}
@Override
public int getOffset() {
return offset;
}
....
}
즉, 저장소 계층을 변경할 필요가 없습니다.서비스 계층을 다음과 같이 변경해야 합니다.
@Service
public class SomethingService {
private SomethingRepository somethingRepository;
@Autowired
public SomethingService(SomethingRepository somethingRepository){
this.somethingRepository = somethingRepository;
}
@Transactional(readOnly=true)
public PageDto getSomething(long somethingElseId, int page, int size){
Page<Something> somethings = somethingRepository.findBySomethingElseId(somethingElseId, new OffsetLimitRequest(offset, limit));
return new PageDto(somethings.getContent()
.stream()
.map(SomethingDto::createDto)
.sorted(comparing(SomethingDto::getDatum))
.collect(toList()), somethings.getTotalElements(), somethings.getTotalPages();
}
}
결과를 수동으로 매핑할 필요는 없으며, 개발에 상당한 시간이 걸릴 것입니다.
언급URL : https://stackoverflow.com/questions/32434058/how-to-implement-pagination-in-spring-boot-with-hibernate
'itsource' 카테고리의 다른 글
요소의 한쪽에 상자 그림자를 추가하려면 어떻게 해야 합니까? (0) | 2023.10.24 |
---|---|
WooCommerce에서 프로그래밍 방식으로 카트 세금 합계 가져오기 (0) | 2023.10.24 |
DTD에서 PCDATA와 CDATA의 차이 (0) | 2023.10.19 |
이미지 이름으로 도커 컨테이너 중지 - Ubuntu (0) | 2023.10.19 |
MySQL에서 ibtmp1 파일을 정리하거나 크기를 조정하는 방법은 무엇입니까? (0) | 2023.10.19 |