Points To Remember



Pagination in Spring Hibernate Application using Bootstrap


  • Create a Domain Person.
  • Create a Service PersonService
  • Create a Dao PersonDao.
  • Create a Controller PersonController.
  • Create a Taglib PaginationTaglib.

Person.java
package com.ekiras.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="person")
public class Person {

public Person(){};
public Person(String name,Integer age){
this.name = name;
this.age = age;
}


@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private Long id;

@Column(name="name")
private String name;

@Column(name="age")
private Integer age;

// GETTERS and SETTERS

PersonService.java
package com.ekiras.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ekiras.dao.PersonDAO;
import com.ekiras.domain.Person;

@Service
public class PersonService {

@Autowired
private PersonDAO personDAO;


public List<Person> list(Integer offset, Integer maxResults){
return personDAO.list(offset, maxResults);
}

public Long count(){
return personDAO.count();
}

public void save(){
personDAO.save();
}

}

PersonDAO.java
package com.ekiras.dao;

import java.util.List;

import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.ekiras.domain.Person;

@Repository
@Transactional
public class PersonDAO {

@Autowired
private SessionFactory sessionFactory;

@SuppressWarnings("unchecked")
@Transactional
public List<Person> list(Integer offset, Integer maxResults){
return sessionFactory.openSession()
.createCriteria(Person.class)
.setFirstResult(offset!=null?offset:0)
.setMaxResults(maxResults!=null?maxResults:10)
.list();
}


public Long count(){
return (Long)sessionFactory.openSession()
.createCriteria(Person.class)
.setProjection(Projections.rowCount())
.uniqueResult();
}


public void save(){
for(int itr=1;itr <= 100 ; itr++){
Person person = new Person("Person_"+itr,Math.max(25, (itr%2)*35));
sessionFactory.openSession()
.save(person);
}



}

}

PersonController.java
package com.ekiras.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ekiras.service.PersonService;

@Controller
@RequestMapping(value="/person")
public class PersonController {

@Autowired
private PersonService personService;

@RequestMapping(value="/list")
public String list(Model model, Integer offset, Integer maxResults){
model.addAttribute("persons", personService.list(offset, maxResults));
model.addAttribute("count", personService.count());
model.addAttribute("offset", offset);
return "/person/list";
}

@RequestMapping(value="/save")
public String save(){
personService.save();
return "/person/list";
}

}

PaginationTaglib.java
package com.ekiras.taglib;

import java.io.Writer;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class PaginationTaglib extends SimpleTagSupport {
private String uri;
private int offset;
private int count;
private int max = 10;
private int steps = 10;
private String previous = "Previous";
private String next = "Next";

private Writer getWriter() {
JspWriter out = getJspContext().getOut();
return out;
}

@Override
public void doTag() throws JspException {
Writer out = getWriter();

try {
out.write("<nav>");
out.write("<ul class=\"pagination\">");

if(offset<steps)
out.write(constructLink(1, previous, "disabled", true));
else
out.write(constructLink(offset-steps, previous, null, false));

for(int itr=0;itr<count;itr+=steps) {
if(offset==itr)
out.write(constructLink((itr/10+1)-1 *steps, String.valueOf(itr/10+1), "active", true));
else
out.write(constructLink(itr/10*steps, String.valueOf(itr/10+1), null , false));
}

if(offset+steps>=count)
out.write(constructLink(offset+steps, next, "disabled", true));
else
out.write(constructLink(offset+steps, next, null , false));


out.write("</ul>");
out.write("</nav>");
} catch (java.io.IOException ex) {
throw new JspException("Error in Paginator tag", ex);
}
}


private String constructLink(int page, String text, String className, boolean disabled) {
StringBuilder link = new StringBuilder("<li");
if (className != null) {
link.append(" class=\"");
link.append(className);
link.append("\"");
}
if(disabled)
link.append(">").append("<a href=\"#\">"+text+"</a></li>");
else
link.append(">").append("<a href=\""+uri+"?offset="+page + "\">"+text+"</a></li>");
return link.toString();
}

public String getUri() {
return uri;
}

public void setUri(String uri) {
this.uri = uri;
}

public int getOffset() {
return offset;
}

public void setOffset(int offset) {
this.offset = offset;
}

public int getCount() {
return count;
}

public void setCount(int count) {
this.count = count;
}

public int getMax() {
return max;
}

public void setMax(int max) {
this.max = max;
}

public String getPrevious() {
return previous;
}

public void setPrevious(String previous) {
this.previous = previous;
}

public String getNext() {
return next;
}

public void setNext(String next) {
this.next = next;
}

public int getSteps() {
return steps;
}

public void setSteps(int steps) {
this.steps = steps;
}

}

list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="tag" uri="/WEB-INF/taglibs/customTaglib.tld"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="/css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css" />
<title>| Ekiras</title>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span> <span
class="icon-bar"></span> <span class="icon-bar"></span> <span
class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>

<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-expanded="false">Dropdown
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
<li class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul></li>
</ul>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-expanded="false">Dropdown
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid --> </nav>

<div class="container">
<div class="well">
<strong>List of Persons</strong>
</div>
<table class="table table-stripped">
<tr>
<th>S.No</th>
<th>Name</th>
<th>Age</th>
</tr>
<c:forEach items="${persons}" var="person" varStatus="itr">
<tr>
<td>${offset + itr.index +1 }</td>
<td>${person.name }</td>
<td>${person.age }</td>
</tr>
</c:forEach>
</table>
<tag:paginate max="15" offset="${offset}" count="${count}"
uri="/person/list" next="&raquo;" previous="&laquo;" />
</div>


<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/bootstrap.min.js"></script>
</body>
</html>

This is how you can do pagination using bootstrap style in spring hibernate mvc application.