codestory

Paginierung in Java Hibernate

  1. Was ist Pagination?
  2. Die Pagination mit Hibernate

1. Was ist Pagination?

Pagination ist eine Technologie zur Trennung einer Liste von mehren Rekorden in die Subliste. Zum Beispiel: Sie suchen nach einem Schlüsselwort auf Google und erhalten die zehntausenden Ergebnisse. Allerdings zeigt jede Seite Google nur 10 Ergebnisse an. Und die anderen Ergebnisse werden in die nächsten Seite angezeigt.
In der Hibernate benutzenden Applikation Java kann ein Query Statement eine Liste von mehren Rekorden zurückgeben und Sie stellen eine Frage, wie nimmt man nur eine Teil der Liste (die Rekorde von der Stelle N1 zur Stelle N2),gleichzeitig schafft die Information von der gesamten Anzahl der Rekorde und der gesamten Anzahl von Seiten
Hibernate vs JPA
Obwohl sind Hibernate und JPA die 2 gleichen Technologie. Wenn Sie Hibernate kennen, können Sie sehr leich mit JPA umgehen und umgekehrt. Allerdings haben wir einigen Unterschiede. Ein davon ist, dass Hibernate die bessere Technologie zur Pagination als JPA bietet. In dieser Unterricht leite ich bei der Verwendung einer Paginationstechnologie von Hibernate 5, Achtung: diese Technologie wird von JPA nicht unterstützt.

2. Die Pagination mit Hibernate

Alles, was Sie machen sollen, ist die Erstellung eines Objekt Query, und das Anbieten der Parameter page, maxResult, maxNavigationResult um ein Objekt PaginationResult zu erstellen.
PaginationResult ist eine Utility Klasse, damit Sie die Liste der den obengemeinten Parameter passenden Rekorden abfragen und zurücknehmen
PaginationResult.java
package org.o7planning.tutorial.hibernate.pagination;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.query.Query;

public class PaginationResult<E> {

    private int totalRecords;
    private int currentPage;
    private List<E> list;
    private int maxResult;
    private int totalPages;

    private int maxNavigationPage;

    private List<Integer> navigationPages;

    // @page: 1, 2, ..
    public PaginationResult(Query<E> query, int page, int maxResult, int maxNavigationPage) {
        final int pageIndex = page - 1 < 0 ? 0 : page - 1;

        int fromRecordIndex = pageIndex * maxResult;
        int maxRecordIndex = fromRecordIndex + maxResult;

        ScrollableResults resultScroll = query.scroll(ScrollMode.SCROLL_INSENSITIVE  );

        List<E> results = new ArrayList<E>();

        boolean hasResult =   resultScroll.first();

        if (hasResult) {
        
            // Scroll to position:
             hasResult = resultScroll.scroll(fromRecordIndex);

            if (hasResult) {
                do {
                    E record = (E) resultScroll.get(0);
                    results.add(record);
                } while (resultScroll.next()//
                        && resultScroll.getRowNumber() >= fromRecordIndex
                        && resultScroll.getRowNumber() < maxRecordIndex);

            }
 
            // Go to Last record.
             resultScroll.last();
        }
 
        // Total Records
        this.totalRecords = resultScroll.getRowNumber() + 1;
        this.currentPage = pageIndex + 1;
        this.list = results;
        this.maxResult = maxResult;

        if (this.totalRecords % this.maxResult == 0) {
            this.totalPages = this.totalRecords / this.maxResult;
        } else {
            this.totalPages = (this.totalRecords / this.maxResult) + 1;
        }

        this.maxNavigationPage = maxNavigationPage;

        if (maxNavigationPage < totalPages) {
            this.maxNavigationPage = maxNavigationPage;
        }
        resultScroll.close();

        this.calcNavigationPages();
    }

    private void calcNavigationPages() {

        this.navigationPages = new ArrayList<Integer>();

        int current = this.currentPage > this.totalPages ? this.totalPages : this.currentPage;

        int begin = current - this.maxNavigationPage / 2;
        int end = current + this.maxNavigationPage / 2;
 
        // The first page
        navigationPages.add(1);
        if (begin > 2) {

    
            // Using for '...'
            navigationPages.add(-1);
        }

        for (int i = begin; i < end; i++) {
            if (i > 1 && i < this.totalPages) {
                navigationPages.add(i);
            }
        }

        if (end < this.totalPages - 2) {
 
            // Using for '...'
            navigationPages.add(-1);
        }
    
        // The last page.
        navigationPages.add(this.totalPages);
    }

    public int getTotalPages() {
        return totalPages;
    }

    public int getTotalRecords() {
        return totalRecords;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public List<E> getList() {
        return list;
    }

    public int getMaxResult() {
        return maxResult;
    }

    public List<Integer> getNavigationPages() {
        return navigationPages;
    }

}
Example:
Employee.java
package org.o7planning.tutorial.hibernate.entities;
 
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
 
@Entity
@Table(name = "EMPLOYEE", //
        uniqueConstraints = { @UniqueConstraint(columnNames = { "EMP_NO" }) })
public class Employee {
 
    @Id
    @Column(name = "EMP_ID")
    private Long empId;
 
    @Column(name = "EMP_NO", length = 20, nullable = false)
    private String empNo;
 
    @Column(name = "EMP_NAME", length = 50, nullable = false)
    private String empName;
 
    @Column(name = "JOB", length = 30, nullable = false)
    private String job;
 
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "MNG_ID")
    private Employee manager;
 
    @Column(name = "HIRE_DATE", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date hideDate;
 
    @Column(name = "SALARY", nullable = false)
    private Float salary;
 
    @Lob
    @Column(name = "IMAGE", length = Integer.MAX_VALUE, nullable = true)
    private byte[] image;
 
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "DEPT_ID", nullable = false)
    private Department department;
 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "empId")
    private Set<Employee> employees = new HashSet<Employee>(0);
 
    // Getter & Setter
 
}
Department.java
package org.o7planning.tutorial.hibernate.entities;
 
import java.util.HashSet;
import java.util.Set;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
 
@Entity
@Table(name = "DEPARTMENT", //
        uniqueConstraints = { @UniqueConstraint(columnNames = { "DEPT_NO" }) })
public class Department {
    @Id
    @Column(name = "DEPT_ID")
    private Integer deptId;
 
    @Column(name = "DEPT_NO", length = 20, nullable = false)
    private String deptNo;
    @Column(name = "DEPT_NAME", nullable = false)
    private String deptName;
 
    @Column(name = "LOCATION")
    private String location;
 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
    private Set<Employee> employees = new HashSet<Employee>(0);
 
    public Department() {
    }  
 
    // Getter & Setter
}
EmployeeInfo.java
package org.o7planning.tutorial.hibernate.beans;

public class EmployeeInfo {

    private Long empId;

    private String empNo;

    private String empName;

    private String deptNo;

    private String deptName;

    public EmployeeInfo() {

    }

    // This constructor is used by Hibernate Query.
    public EmployeeInfo(Long empId, String empNo, String empName, String deptNo, String deptName) {
        this.empId = empId;
        this.empNo = empNo;
        this.empName = empName;
        this.deptNo = deptNo;
        this.deptName = deptName;
    }

    // Getter & Setter
}
Example:
PaginationExample1.java
package org.o7planning.tutorial.hibernate.pagination;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class PaginationExample1 {

    public static void main(String[] args) {

        // Have sessionFactory object...
        SessionFactory factory = HibernateUtils.getSessionFactory();

        Session session = factory.getCurrentSession();

        String sql = "Select e from " + Employee.class.getName() + " e " //
                + " Where e.empId > :empId ";
        Query<Employee> query = session.createQuery(sql, Employee.class);
        query.setParameter("empId", 100);

        int page = 1;
        int maxResult = 20;
        int maxNavigationResult = 10;

        PaginationResult<Employee> result = new PaginationResult<Employee>(query, page, maxResult, maxNavigationResult);

        // Result:
        List<Employee> emps = result.getList();
        int totalPages = result.getTotalRecords();
        int totalRecords = result.getTotalRecords();

        // 1 2 3 4 5 ... 11 12 13
        List<Integer> navPages = result.getNavigationPages();

    }

}
Example:
PaginationExample2.java
package org.o7planning.tutorial.hibernate.pagination;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.o7planning.tutorial.hibernate.HibernateUtils;
import org.o7planning.tutorial.hibernate.beans.EmployeeInfo;
import org.o7planning.tutorial.hibernate.entities.Employee;

public class PaginationExample2 {

    public static void main(String[] args) {

        // Get sessionFactory object...
        SessionFactory factory = HibernateUtils.getSessionFactory();

        Session session = factory.getCurrentSession();

        String sql = "Select new " + EmployeeInfo.class.getName() //
                + " (e.empId,e.empNo,e.empName,d.deptNo,d.deptName) " //
                + " from " + Employee.class.getName() + " e " //
                + " Join e.department d " //
                + " Order by e.empNo ";
        Query<EmployeeInfo> query = session.createQuery(sql, EmployeeInfo.class);

        int page = 1;
        int maxResult = 20;
        int maxNavigationResult = 10;

        PaginationResult<EmployeeInfo> result
             = new PaginationResult<EmployeeInfo>(query, page, maxResult, maxNavigationResult);

        // Result:
        List<EmployeeInfo> emps = result.getList();
        int totalPages = result.getTotalRecords();
        int totalRecords = result.getTotalRecords();

        // 1 2 3 4 5 ... 11 12 13
        List<Integer> navPages = result.getNavigationPages();

    }

}
Und ein Beispiel .... ein Kode Stück JSP mit der Verwendung von PaginationResult
JSP Pagination
<c:if test="${paginationProducts.totalPages > 1}">
   <div class="page-navigator">
      <c:forEach items="${paginationProducts.navigationPages}" var = "page">
         <c:if test="${page != -1 }">
            <a href="productList?page=${page}" class="nav-item">${page}</a>
         </c:if>
         <c:if test="${page == -1 }">
            <span class="nav-item"> ... </span>
         </c:if>
      </c:forEach>
   </div>
</c:if>