itsource

동면 상태의 스프링 부츠에서 호출을 구현하는 방법

mycopycode 2023. 10. 24. 21:18
반응형

동면 상태의 스프링 부츠에서 호출을 구현하는 방법

동면 상태에서 스프링부츠를 사용하고 있는데 프로젝트에서 페이지네이션을 사용하고 싶습니다.구글에서 검색해보니 많은 예시를 보았지만 프로젝트에서 구현할 수 없습니다.

제 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

반응형