Showing posts with label dao. Show all posts
Showing posts with label dao. Show all posts

Friday, April 3, 2009

Generic Data Access Objects with Pagnation under Spring and Hibernate Framework

Page.java
import java.util.List;

public class Page<T> {
private List<T> rowsInPage;
private int pageSize;
private int pageNo;
private int totalRows;

/**
*
* @param pageNo
* @param pageSize
* @param rowsInPage
* @param totalRows
*/
public Page(int pageNo, int pageSize, List<T> rowsInPage, int totalRows) {
if(pageSize > 0){
this.pageNo = (pageNo > 0) ? pageNo : 1;
this.pageSize = pageSize;
this.rowsInPage = rowsInPage;
this.totalRows = totalRows;
}else if(pageSize == 0){
this.pageNo = 0;
this.pageSize = 0;
this.rowsInPage = null;
this.totalRows = 0;
}else{
this.pageNo = 1;
this.pageSize = -1;
this.rowsInPage = rowsInPage;
this.totalRows = -1;
}
}

/**
*
* @return
*/
public boolean hasNext() {
return getPages() > pageNo;
}

/**
*
* @return
*/
public boolean hasPrevious() {
return pageNo > 1;
}

/**
*
* @return
*/
public List<T> getRowsInPage() {
return rowsInPage;
}

/**
*
* @return
*/
public int getPageSize() {
return pageSize;
}

/**
*
* @return
*/
public int getPageNo() {
return pageNo;
}

/**
*
* @return
*/
public int getTotalRows() {
return totalRows;
}

/**
*
* @return
*/
public int getPages() {
if(totalRows > 0)
return (totalRows%pageSize == 0) ? totalRows / pageSize : totalRows / pageSize + 1;
else if(totalRows == 0)
return 0;
else
return 1;
}
}


GenericDAO.java
import java.io.Serializable;
import org.hibernate.criterion.Order;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.aais.core.utils.Page;

@Transactional(rollbackFor=Exception.class)
public interface GenericDAO<T, ID extends Serializable> {

/**
*
* @param id
* @param lock
* @return
*/
@Transactional(readOnly=true)
public T findById(ID id, boolean lock);

/**
*
* @param pageNo
* @param pageSize
* @param order
* @return
*/
@Transactional(readOnly=true)
public Page<T> findAll(int pageNo, int pageSize, Order order);

/**
*
* @param pageNo
* @param pageSize
* @param exampleInstance
* @param order
* @param excludeProperty
* @return
*/
@Transactional(readOnly=true)
public Page<T> findByExample(int pageNo, int pageSize, T exampleInstance, Order order, String[] excludeProperty);

/**
*
* @param pageNo
* @param pageSize
* @param queryName
* @param paramNames
* @param values
* @return
*/
@Transactional(readOnly=true)
public Page<T> findByHQL(int pageNo, int pageSize, String queryName, String[] paramNames, Object[] values);

/**
*
* @param entity
* @return
*/
@Transactional(propagation=Propagation.REQUIRED)
public T saveOrUpdate(T entity);

/**
*
* @param entity
*/
@Transactional(propagation=Propagation.REQUIRED)
public void delete(T entity);
}


GenericDAOHibernateImpl.java
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.aais.core.dao.GenericDAO;
import com.aais.core.utils.Page;

public abstract class GenericDAOHibernateImpl<T, ID extends Serializable> extends HibernateDaoSupport implements GenericDAO<T, ID> {

private Class<T> persistentClass;
private final static Log logger = LogFactory.getLog(GenericDAOHibernateImpl.class);

/**
*
*/
@SuppressWarnings("unchecked")
public GenericDAOHibernateImpl() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

/**
*
* @return
*/
public Class<T> getPersistentClass() {
return persistentClass;
}

/**
* (pageNo > 0 && pageSize > 0) paginate
* (pageNo < 0 && pageSize < 0) don't paginate
*/
public Page<T> findAll(int pageNo, int pageSize, Order order) {
return findByCriteria(pageNo, pageSize, order, (Criterion[])null);
}

/**
* (pageNo > 0 && pageSize > 0) paginate
* (pageNo < 0 && pageSize < 0) don't paginate
*/
@SuppressWarnings("unchecked")
protected Page<T> findByCriteria(int pageNo, int pageSize, Order order, Criterion...criterion) {
Criteria crit = getCriteria();
if(criterion != null){
for (Criterion c : criterion) {
crit.add(c);
}
}
if(order != null)
crit.addOrder(order);
int rowCount = 0;
if(pageSize > 0){
rowCount = (Integer) ((Criteria) crit.setProjection(Projections.rowCount())).uniqueResult();
crit.setProjection(null);
if(pageNo < 1)
pageNo = 1;
((Criteria) crit).setFirstResult((pageNo - 1) * pageSize);
((Criteria) crit).setMaxResults(pageSize);
if(pageSize > rowCount)
pageSize = rowCount;
}
crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<T> list = crit.list();
return new Page<T>(pageNo, pageSize, list, rowCount);
}

/**
*
* @return
*/
protected Criteria getCriteria(){
Criteria crit = this.getSession().createCriteria(getPersistentClass());
return crit;
}

/**
* (pageNo > 0 && pageSize > 0) paginate
* (pageNo < 0 && pageSize < 0) don't paginate
*/
@SuppressWarnings("unchecked")
protected Page<T> findByCriteria(int pageNo, int pageSize, Criteria crit, Order order){
if(order != null)
crit.addOrder(order);
int rowCount = 0;
if(pageSize > 0){
rowCount = (Integer) ((Criteria) crit.setProjection(Projections.rowCount())).uniqueResult();
crit.setProjection(null);
if(pageNo < 1)
pageNo = 1;
((Criteria) crit).setFirstResult((pageNo - 1) * pageSize);
((Criteria) crit).setMaxResults(pageSize);
if(pageSize > rowCount)
pageSize = rowCount;
}
crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<T> list = crit.list();
return new Page<T>(pageNo, pageSize, list, rowCount);
}

/**
* (pageNo > 0 && pageSize > 0) paginate
* (pageNo < 0 && pageSize < 0) don't paginate
*/
@SuppressWarnings("unchecked")
public Page<T> findByExample(int pageNo, int pageSize, T exampleInstance, Order order, String[] excludeProperty) {
Criteria crit = getCriteria();
Example example = Example.create(exampleInstance).enableLike();
if(excludeProperty != null){
for (String exclude : excludeProperty) {
example.excludeProperty(exclude);
}
}
crit.add(example);
if(order != null)
crit.addOrder(order);
int rowCount = 0;
if(pageSize > 0){
rowCount = (Integer) ((Criteria) crit.setProjection(Projections.rowCount())).uniqueResult();
crit.setProjection(null);
if(pageNo < 1)
pageNo = 1;
((Criteria) crit).setFirstResult((pageNo - 1) * pageSize);
((Criteria) crit).setMaxResults(pageSize);
if(pageSize > rowCount)
pageSize = rowCount;
}
crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<T> list = crit.list();
return new Page<T>(pageNo, pageSize, list, rowCount);
}

/**
*
*/
public T findById(ID id, boolean lock) {
T entity = null;
if (lock)
entity = (T) getHibernateTemplate().get(getPersistentClass(), id, LockMode.UPGRADE);
else
entity = (T) getHibernateTemplate().get(getPersistentClass(), id);
if(entity == null){
logger.warn("Could not find out " + getPersistentClass().getName() + " instance with id=" + id);
}else{
if(logger.isDebugEnabled())
logger.debug("Getting "+getPersistentClass().getName()+" instance with id: " + id);
}
return entity;
}

/**
*
* @param queryName
* @param paramNames
* @param values
* @return
*/
private Query createQuery(String queryName, String[] paramNames, Object[] values) {
Query query = getSession().getNamedQuery(queryName);
query.setCacheable(true);
if ((paramNames != null) && (values != null)) {
for (int i = 0; i < paramNames.length; i++) {
query.setParameter(paramNames[i], values[i]);
}
}
return query;
}

/**
* (pageNo > 0 && pageSize > 0) paginate
* (pageNo < 0 && pageSize < 0) don't paginate
* don't use for full table paginate, that would be low efficency
*/
@SuppressWarnings("unchecked")
public Page<T> findByHQL(int pageNo, int pageSize, String queryName, String[] paramNames, Object[] values){
long rowCount = 0;
Query query = createQuery(queryName, paramNames, values);
if(pageSize > 0){
rowCount = ((Long)getRowCountByHQL(appendRowCountHQL(queryName), paramNames, values)).longValue();
if(pageNo < 1)
pageNo = 1;
if(pageSize > rowCount)
pageSize = (int)rowCount;
query.setFirstResult((pageNo - 1) * pageSize);
query.setMaxResults(pageSize);
}
List<T> list = query.list();
return new Page<T>(pageNo, pageSize, list, (int)rowCount);
}

/**
*
* @param queryName
* @return
*/
private String appendRowCountHQL(String queryName){
return queryName + ".Count";
}

/**
*
* @param queryName
* @param paramNames
* @param values
* @return
*/
@SuppressWarnings("unchecked")
private Object getRowCountByHQL(final String queryName, final String[] paramNames, final Object[] values) {
return ((Object) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = createQuery(queryName, paramNames, values);
if (paramNames != null && values != null && paramNames.length == values.length) {
for (int i = 0, max = paramNames.length; i < max; i++) {
query.setParameter(paramNames[i], values[i]);
}
}
return query.uniqueResult();
}
}));
}


/**
*
*/
public T saveOrUpdate(T entity) throws DataIntegrityViolationException{
getHibernateTemplate().saveOrUpdate(entity);
return entity;
}

/**
*
*/
public void delete(T entity) {
getHibernateTemplate().delete(entity);
}
}