Close

Java Swing - JTable Lazy Pagination with JPA

[Last Updated: Jul 4, 2018]

This example shows how to do lazy pagination with JTable. The data will be retrieved from JPA backend on demand. We will use Hibernate as JPA provider and H2 in-memory database. The JTable will also have sorting functionality like the last example.

Main class

public class PaginationExampleMain {
    public static void main(String[] args) {
        JFrame frame = createFrame();
        ObjectTableModel<Employee> objectDataModel = createObjectDataModel();
        JTable table = new JTable(objectDataModel);
        table.setAutoCreateRowSorter(true);
        PaginationDataProvider<Employee> dataProvider = createDataProvider(objectDataModel);
        PaginatedTableDecorator<Employee> paginatedDecorator = PaginatedTableDecorator.decorate(table,
                dataProvider, new int[]{5, 10, 20, 50, 75, 100}, 10);
        frame.add(paginatedDecorator.getContentPanel());
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static ObjectTableModel<Employee> createObjectDataModel() {
        return new ObjectTableModel<Employee>() {
            @Override
            public Object getValueAt(Employee employee, int columnIndex) {
                switch (columnIndex) {
                    case 0:
                        return employee.getId();
                    case 1:
                        return employee.getName();
                    case 2:
                        return employee.getPhoneNumber();
                    case 3:
                        return employee.getAddress();
                }
                return null;
            }

            @Override
            public int getColumnCount() {
                return 4;
            }

            @Override
            public String getColumnName(int column) {
                switch (column) {
                    case 0:
                        return "Id";
                    case 1:
                        return "Name";
                    case 2:
                        return "Phone Number";
                    case 3:
                        return "Address";
                }
                return null;
            }

            @Override
            public String getFieldName(int column) {
                switch (column) {
                    case 0:
                        return "id";
                    case 1:
                        return "name";
                    case 2:
                        return "phoneNumber";
                    case 3:
                        return "address";
                }
                return null;
            }
        };
    }

    private static PaginationDataProvider<Employee> createDataProvider(
            ObjectTableModel<Employee> objectDataModel) {

        return new EmployeeLazyDataProvider(objectDataModel);
    }

    private static JFrame createFrame() {
        JFrame frame = new JFrame("JTable Pagination example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(600, 300));
        return frame;
    }
}

PaginationDataProvider implementation

public class EmployeeLazyDataProvider implements PaginationDataProvider<Employee> {
    private final int totalEmployeeCount;
    private final ObjectTableModel<Employee> objectTableModel;

    public EmployeeLazyDataProvider(ObjectTableModel<Employee> objectTableModel) {
        this.objectTableModel = objectTableModel;
        this.totalEmployeeCount = DataService.INSTANCE.getEmployeeTotalCount();
    }

    @Override
    public int getTotalRowCount() {
        return totalEmployeeCount;
    }

    @Override
    public List<Employee> getRows(int startIndex, int endIndex, int sortColumnIndex, boolean sortDescending) {
        String fieldName = sortColumnIndex != -1 ?
                objectTableModel.getFieldName(sortColumnIndex) : null;
        return DataService.INSTANCE.getEmployeeList(
                startIndex,  endIndex - startIndex , fieldName, sortDescending);
    }
}

Employee class with JPA annotations

@Entity
public class Employee {
    @Id
    @SequenceGenerator(name = "eSGen", sequenceName = "employeeSeq",
            initialValue = 50)
    @GeneratedValue(generator = "eSGen")
    private long id;
    private String name;
    private String phoneNumber;
    private String address;

    public long getId () {
        return id;
    }

    public void setId (long id) {
        this.id = id;
    }

    public String getName () {
        return name;
    }

    public void setName (String name) {
        this.name = name;
    }

    public String getPhoneNumber () {
        return phoneNumber;
    }

    public void setPhoneNumber (String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getAddress () {
        return address;
    }

    public void setAddress (String address) {
        this.address = address;
    }
}

The pagination decorator

There's no change with the decorator from the last example.

JPA data service

public enum DataService {
    INSTANCE;
    private final EntityManagerFactory emf =
            Persistence.createEntityManagerFactory("employee-unit");

    DataService() {
        //persisting some test data in database
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        DataFactory dataFactory = new DataFactory();
        for (int i = 1; i < 100; i++) {
            Employee employee = new Employee();
            employee.setName(dataFactory.getName());
            employee.setPhoneNumber(String.format("%s-%s-%s", dataFactory.getNumberText(3),
                    dataFactory.getNumberText(3),
                    dataFactory.getNumberText(4)));
            employee.setAddress(dataFactory.getAddress() + "," + dataFactory.getCity());
            em.persist(employee);
        }

        em.getTransaction().commit();
        em.close();
    }

    public List<Employee> getEmployeeList(int start, int size,
                                          String sortField, boolean sortDescending) {
        EntityManager em = emf.createEntityManager();
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Employee> q = cb.createQuery(Employee.class);
        Root<Employee> r = q.from(Employee.class);
        CriteriaQuery<Employee> select = q.select(r);
        if (sortField != null) {
            q.orderBy(sortDescending ?
                    cb.desc(r.get(sortField)) : cb.asc(r.get(sortField)));
        }

        TypedQuery<Employee> query = em.createQuery(select);
        query.setFirstResult(start);
        query.setMaxResults(size);
        List<Employee> list = query.getResultList();
        return list;
    }

    public int getEmployeeTotalCount() {
        EntityManager em = emf.createEntityManager();
        Query query = em.createQuery("Select count(e.id) From Employee e");
        return ((Long) query.getSingleResult()).intValue();
    }
}

Output

Example Project

Dependencies and Technologies Used:

  • h2 1.4.196: H2 Database Engine.
  • hibernate-core 5.2.12.Final: The core O/RM functionality as provided by Hibernate.
    Implements javax.persistence:javax.persistence-api version 2.1
  • datafactory 0.8: Library to generate data for testing.
  • JDK 1.8
  • Maven 3.3.9

JTable lazy Pagination with Sorting Example Select All Download
  • table-lazy-pagination-with-jpa
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • EmployeeLazyDataProvider.java
          • resources
            • META-INF

    See Also