How to implement pagination in spring boot with hibernate

后端 未结 5 1034
野的像风
野的像风 2020-12-15 07:21

I am using spring boot with hibernate and I want to use pagination in my project. I have searched on google and saw many examples but I am unable to implement it in my proje

相关标签:
5条回答
  • 2020-12-15 07:50

    I would consider using org.springframework.data.domain.Pageable directly into your controller. This object can then be passed to your JPA layer where it will handle the number of returned results and the size.

    The great thing about using Pageable is that it returns a Page object which can be used on the front-end to form previous/next page logic.

    By default this class uses url parameters 'page' and 'size'; hence page=0&size=10 will return the first 10 items.

    Hence in your case the code could look something like:

    @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();
    }
    

    Notice the annotation @PageableDefault is just to set up the defaults & it's not required.

    In the front-end the next page call can be <a href="/top/pages?page=1">Next</a>; this will return a list of Posts from 11 to 20.

    0 讨论(0)
  • 2020-12-15 07:53

    I have implemented pagination in spring boot. Below is my Repository.

        @Repository("userRepository")
        public interface UserRepository extends PagingAndSortingRepository<User, Long> {
      }
    

    Below is my Controller.

    @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";
        }
    }
    

    Below is the view,for that I have used thymeleaf.

    <!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>
    
    0 讨论(0)
  • 2020-12-15 07:57

    Implement pagination in Spring Boot is quite easy only you need to follow basic steps -

    1 - Extends PagingAndSortingRepository in repository interface

    public interface UserRepository extends PagingAndSortingRepository <User, Long> 
    

    2 - Method declaration should be like below example

    Page<User> userList(Pageable pageable);
    

    3 - Method implementation in Service class should be like below example

    @Override
    public Page<User> userList(Pageable pageable) {
            return userRepository.findAll(pageable);
    }
    

    4 - Controller class code should be like below

    @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";
    }
    

    From front-end call should be like below

    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
    

    For more details watch below video

    Spring Boot : Pagination Basic

    Spring Boot : Pagination Advanced

    Thanks for reading

    0 讨论(0)
  • 2020-12-15 08:00

    How to Implement Dynamic Pagination Using a Native Query

    Here, you can find the repository and service layers and your data transfer object (DTO), which will be used for mapping our result and sending it to the controller layer.

    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 translates your query as follows:

    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;
        }
    }
    

    Pros and Cons Pros: Fewer SQL queries will be generated, compared to using Spring Data. These complex queries cannot be written in Spring Data, and we have to specify our query as a native one, which can still be paged by using this methodology.

    Cons: The "object" array must map to a Java object. It is painful and hard to maintain.

    How to Implement OffsetLimit Pagination With Spring Data As far as I know, there is no "out-of-the-box" support for what you need in default Spring Data repositories. But you can create a custom implementation of Pageable objects that will take limit/offset parameters.

    Make a pageable object and pass it to 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;
        }
        ....
    }
    

    It means there is no need to change the repository layer. The only change you would need is to make is to the service layer, as follows:

    @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();
        }
    }
    

    Note that you don't need to map the result manually, and it will take off a good amount of time from development.

    0 讨论(0)
  • 2020-12-15 08:16

    Check it. Your controller

    @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;
    }
    

    Your 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";
    }
    
    0 讨论(0)
提交回复
热议问题