Follow me

Saturday, December 7, 2013

Pagination Using Spring 3.1 + Spring JPA Repository + JQuery


Performance and presentation is very critical factor while developing the web application and when you have to display 1000s of records on single web page it become very difficult and frustrating thing for end user to wait and view this records having long scroll bar.

In such case we all remember a very famous example like this J







Situation demands pagination when
·         When there is more data than what is comfortably fitted into one screen.
·         When the dataset is ordered into amount of interest (that usually means newest first)

And

·         Do not use when you don’t want the user to pause for navigating to the next page.

So the solution is

Break the complete dataset of items into smaller sequential parts and show these on separate sequential pages. Provide pagination control to browse from page to page. Let the user browse to the previous and next pages by providing links to such actions. Also, provide links to the absolute start and end of the dataset (first and last).

If the dataset is of defined quantity, also show a link to the last page. If the dataset to show possibly is of varying size (for instance as a result from a search), do not bother to show a link to the last page.


So in this article I will show you how you will get this using spring 3.1 and its JPA API’s

Here we are going to use below JQuery libraries and some minimum require spring jars for pagination
For JQuery libraries go to https://github.com/flaviusmatis/simplePagination.js click on Project Page to download below js and css files
  • jquery.simplePagination.js
  • simplePagination.css


For actual pagination using Spring API we are using below jars
·         spring-web-3.1.0.RELEASE-sources.jar controller
·         spring-data-jpa-1.1.0.RELEASE-sources.jar
·         spring-data-commons-core-1.3.0.RELEASE-sources.jar

On GUI side we are using JSP to display the records; here I am going to paste needful code only
1)      Include the simplePagination.css and  jquery.simplePagination.js in your JSP


<script type="text/javascript" src="resources/scripts/jquery.simplePagination.js"/>

<link rel="stylesheet" type="text/css" href="resources/css/simplePagination.css" />


2)  Add the div with any id. This div will work as a place holder for the pagination  shown below






<div id="simplePaginationAbove" style="display: none;"></div>



3) Add below JQuery function. This will get called on your pagination placeholder.
    Note:-  element #simplePaginationAbove  is a div id mentioned above.
    here
   itemsOnPage: - Default: 1 Number of items displayed on each page (here 10).
   Pages: - total pages [this will be outcome of no of record return by query]


<script type="text/javascript">

       $(function() {

              $("#simplePaginationAbove")
              .pagination(
                     {
              //items: 100,
              itemsOnPage : 10,
              cssStyle : 'light-theme',
              //pages: '${endIndex}',
              pages : document.getElementById("totalPage").value,
              //currentPage: '${currentIndex}',
              currentPage : '${allStudentModel.pageNumber}',
              onPageClick : function(pageNumber, event) {
              document.getElementById('allStudents').action = "/app/allStudents";
              document.getElementById("pageNumber").value = pageNumber;
              document.getElementById('allStudents').submit();
              }

              });
       });

</script>


On click event on this component will act as a new page request to controller with given request parameter

4) I am storing this currentPage, pages value as hidden form variable.


<input type="hidden" id="totalPage" name="totalPage"
                                                value="${allStudentModel.totalPage}" /> <input type="hidden" id="pageNumber" name="pageNumber"
                                                value="${allStudentModel.pageNumber}" />

5)  You can use any display logic that you want like below

<c:forEach  var="student" items="${ allStudentModel.students }" > </c:forEach>

Now Our GUI is ready let’s move to the controller and service layer where actual pagination configured

6)  This is our controller which will serve our request. I am just passing the collection of student.


@RequestMapping(value = "/allStudents", method = RequestMethod.GET)
       public @ModelAttribute("students")
       Collection<StudentVo> getAllStudents(HttpServletRequest request,
              @ModelAttribute("allStudentModel") AllStudentModel allStudentModel) {
              students = studentService. findAll(allStudentModel);
              return students;
       }

allStudentModel will hold our pagination value which I am setting to our service.

7) Below is the service method where we are actually doing pagination, here we are creating the new PageRequest object by passing page size, sorting order and page no.  And again update the model object with current page no. and total pages from the Page array to keep track of pagination values. 
This Pageable is the page that we required.

      @Override
       public List<StudentVo> findAll(StudentModel model) {
       int pageNumber = Integer.parseInt(model.getPageNumber());
       int pageSize = Integer.parseInt(model.getPageSize());
       //org.springframework.data.domain.Pageable
       //org.springframework.data.domain.PageRequest.PageRequest
       Pageable request = new PageRequest(pageNumber - 1, pageSize, Sort.Direction.DESC, "id");
       Page<Student> allStudent = studentRepository.findAll(request);
       model.setTotalPage(Integer.toString(allStudent.getTotalPages()));
       model.setPageNumber(Integer.toString(pageNumber));
             
//Here apply your own logic to convert Entity/Persistent class (here Page<Student>) into VO or the list of object you want to send on GUI for display.
//Here we are converting it into VO'S value object since we don't expose entity bean on View
              List<StudentVo> vos = new ArrayList<StudentVo>();
              for (Student student : allStudent) {
                     StudentVo studentVo = builder.buildStudentVoFromEntity(student);
                     vos.add(studentVo);
              }
              return vos;
       }

8)   As you all know Spring implements the data access layer facility using JPA repository which manage Domain object. Domain repositories extend this Repository and perform any CRUD operation by simply declaring methods of the same signature as those declared in CrudRepository. So the below method declare will be implemented by the spring data module so this will do the rest job

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import com.app.daos.entities.Student;

public interface StudentRepository extends JpaRepository<Student, Long> {}
      Page<Student>  findAll(Pageable page);
}

And you will get below pagination control on GUI





1 comment:

  1. what is AllStudentModel here ?
    also are you doing a form submit for "allStudents", which I am assuming a form variable ?

    ReplyDelete