import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Criterion;
/**
*
* Hibernate Generic DAO Interface
*
* @param <T> Entity
* @param <PK> Primary Key
*/
public interface GenericDaoIf<T, PK extends Serializable> {
/**
* Get entity by primary key
* @param id Primary key
* @return Entity object
*/
public T get(final PK id);
/**
* Load entity by primary key
* @param id Primary key
* @return Entity object
*/
public T load(final PK id);
/**
* Remove entity from session, changes to this entity will
* not be synchronized with the database
* @param entity The object to be evicted
*/
public void evict(T entity);
/**
* Save entity
* @param entity The object to be saved
* @return The generated identifier
*/
public PK save(T entity);
/**
* Update entity
* @param entity The object to be updated
*/
public void update(T entity);
/**
* Save or update entity
* @param entity The object to be save or update
*/
public void saveOrUpdate(T entity);
/**
* Update entity's not-null property
* (this entity must have a primary key property "id")
* @param entity The object to be updated
*/
public void updateSelective(T entity);
/**
* Merge entity
* @param entity The object to be merged into database
* @return The persistent object
*/
public T merge(T entity);
/**
* Delete entity (actually, delete by primary key)
* @param entity The object to be deleted
*/
public void delete(T entity);
/**
* Delete entity by primary key, first get then delete
* @param id Primary key
*/
public void delete(PK id);
/**
* Find all entities
* @return Query result list
*/
public List<T> findAll();
/**
* Find entities by page
* @param page Paging object
* @return Paging query result, Comes with a results list
*/
public Page<T> findAll(Page<T> page);
/**
* Press the HQL Query object list
* @param hql
* HQL statement
* @param values
* Number of variable parameters
* @return Query result list
*/
public List<T> find(String hql, Object... values);
/**
* Press the SQL Query object list
* @param sql
* SQL statement
* @param values
* Number of variable parameters
* @return Query result list
*/
public List<T> findBySql(String sql, Object... values);
/**
* Press the HQL query paging .
* @param page
* Paging parameters .
* @param hql
* HQL statement .
* @param values
* Number of variable parameters .
* @return Paging query results ,Comes with a results list .
*/
public Page<T> find(Page<T> page, String hql, Object... values);
/**
* Press the SQL query paging .
* @param page
* Paging parameters .
* @param sql
* SQL statement .
* @param values
* Number of variable parameters .
* @return Paging query results ,Comes with a results list .
*/
public Page<T> findBySql(Page<T> page, String sql, Object... values);
/**
* Press the HQL query only object
* @param hql
* HQL statement
* @param values
* Number of variable parameters
* @return A single instance that matches the query, or null if the query returns no results
*/
public Object findUnique(String hql, Object... values);
/**
* Press the SQL query only object
* @param sql
* SQL statement
* @param values
* Number of variable parameters
* @return A single instance that matches the query, or null if the query returns no results
*/
public Object findUniqueBySql(String sql, Object... values);
/**
* According to the Criterion query object list .
* @param criterion
* Number of variable Criterion .
* @return Query result list
*/
public List<T> findByCriteria(Criterion... criterion);
/**
* According to the Criterion paging query .
* @param page
* Paging parameters .Including the pageSize, firstResult, orderBy, asc, autoCount .
* Where firstResult can be directly specified ,You can also specify pageNo . autoCountSpecifies whether dynamic gets total number of results .
* @param criterion
* Number of variable criterion .
* @return Paging query results .Comes with a results list and all query parameters .
*/
public Page<T> findByCriteria(Page<T> page, Criterion... criterion);
/**
* Find a list of objects by property .
* @param propertyName Property name of the entity
* @param value Property value
* @return Query result list
*/
public List<T> findByProperty(String propertyName, Object value);
/**
* Find unique object by property .
* @param propertyName Property name of the entity
* @param value Property value
* @return A single instance that matches the query, or null if the query returns no
*/
public T findUniqueByProperty(String propertyName, Object value);
/**
* Determine the object's property value is unique within the database .
* @param propertyName Property name of the entity
* @param newValue New property value
*/
public boolean isPropertyUnique(String propertyName, Object newValue);
/**
* Depending on the query function and argument list to create a Query object ,Subsequent to processing ,The auxiliary function .
* @param queryString HQL string
* @param values Number of variable parameters
* @return Query object
*/
public Query createQuery(String queryString, Object... values);
/**
* Depending on the query function and argument list to create a SQL Query object ,Subsequent to processing ,The auxiliary function .
* @param queryString SQL string
* @param values Number of variable parameters
* @return SQL query object
*/
public SQLQuery createSQLQuery(String queryString, Object... values);
/**
* According to the Criterion conditions create Criteria ,Subsequent to processing ,The auxiliary function .
* @param criterions Number of variable criterion
* @return A criteria
*/
public Criteria createCriteria(Criterion... criterions);
/**
* Count HQL query result
* @param hql HQL statement
* @param values Number of variable parameters
* @return Result count
*/
public long countQueryResult(String hql, Object... values);
/**
* Count SQL query result
* @param sql HQL statement
* @param values Number of variable parameters
* @return Result count
*/
public long countSQLQueryResult(String sql, Object... values);
/**
* Through this count query to obtain the total number of objects .
* @param page Paging object
* @param c Query criteria
* @return The total number of objects of the query result.
*/
public long countCriteriaResult(Page<T> page, Criteria c);
/**
* Save entities in batch
* @param entities The objects to be saved
* @param batchSize The number of every session flush
* @return Successful save count
*/
public int batchSave(List<T> entities, int batchSize);
/**
* Update entities in batch
* @param entities The objects to be updated
* @param batchSize The number of every session flush
* @return Successful update count
*/
public int batchUpdate(List<T> entities, int batchSize);
/**
* Save or update entities in batch
* @param entities The objects to be saved or updated
* @param batchSize The number of every session flush
* @return Successful save count or update count
*/
public int batchSaveOrUpdate(List<T> entities, int batchSize);
/**
* Update entities (not-null property) in batch
* @param entities The objects to be updated
* @param batchSize The number of every session flush
* @return Successful update count
*/
public int batchUpdateSelective(List<T> entities, int batchSize);
/**
* Merge entities in batch
* @param entities The objects to be merged
* @param batchSize The number of every session flush
* @return Successful merge count
*/
public int batchMerge(List<T> entities, int batchSize);
/**
* Delete entities in batch
* @param entities The objects to be deleted
* @param batchSize The number of every session flush
* @return successful delete count
*/
public int batchDelete(List<T> entities, int batchSize);
}
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.OrderEntry;
import org.hibernate.transform.ResultTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import com.alan.mvnapp.mvn_app.dao.GenericDaoIf;
import com.alan.mvnapp.mvn_app.dao.Page;
/**
*
* Hibernate Generic DAO Implementation
*
* @param <T> Entity
* @param <PK> Primary Key
*/
public class GenericDaoImpl<T, PK extends Serializable> implements GenericDaoIf<T, PK> {
protected Logger logger = LoggerFactory.getLogger(getClass());
protected SessionFactory sessionFactory;
protected Class<?> entityClass;
public GenericDaoImpl() {
this.entityClass = (Class<?>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public GenericDaoImpl(SessionFactory sessionFactory, Class<T> entityClass) {
this.sessionFactory = sessionFactory;
this.entityClass = entityClass;
}
@SuppressWarnings("unchecked")
public T get(final PK id) {
return (T) sessionFactory.getCurrentSession().get(entityClass, id);
}
@SuppressWarnings("unchecked")
public T load(final PK id) {
return (T) sessionFactory.getCurrentSession().load(entityClass, id);
}
public void evict(T entity) {
sessionFactory.getCurrentSession().evict(entity);
}
@SuppressWarnings("unchecked")
public PK save(T entity) {
Assert.notNull(entity);
PK pk = (PK) sessionFactory.getCurrentSession().save(entity);
logger.info("save entity: {}", entity);
return pk;
}
public void update(T entity) {
Assert.notNull(entity);
sessionFactory.getCurrentSession().update(entity);
logger.info("update entity: {}", entity);
}
public void saveOrUpdate(T entity) {
Assert.notNull(entity);
sessionFactory.getCurrentSession().saveOrUpdate(entity);
logger.info("save or update entity: {}", entity);
}
public void updateSelective(T entity) {
Assert.notNull(entity);
Field[] fields = entity.getClass().getDeclaredFields();
List<String> params = new ArrayList<String>();
List<Object> values = new ArrayList<Object>();
for(Field field : fields) {
String fieldName = field.getName();
field.setAccessible(true);
Object value = ReflectionUtils.getField(field, entity);
if(value != null) {
params.add(fieldName);
values.add(value);
}
}
if(!params.isEmpty()) {
StringBuffer sb = new StringBuffer("update "
+ entityClass.getSimpleName() + " set ");
for(int i = 0; i < params.size(); i++) {
sb.append(params.get(i) + " = ? ");
if(i < params.size() - 1) {
sb.append(", ");
}
}
Field pkField = ReflectionUtils.findField(entityClass, "id");
Assert.notNull(pkField);
pkField.setAccessible(true);
sb.append(" where id = ? ");
values.add(ReflectionUtils.getField(pkField, entity));
createQuery(sb.toString(), values.toArray()).executeUpdate();
logger.info("update entity selecitive: {}" + entity);
}
}
@SuppressWarnings("unchecked")
public T merge(T entity) {
Assert.notNull(entity);
T t = (T) sessionFactory.getCurrentSession().merge(entity);
logger.info("merge entity: {}", entity);
return t;
}
public void delete(T entity) {
Assert.notNull(entity);
sessionFactory.getCurrentSession().delete(entity);
logger.info("delete entity: {}", entity);
}
public void delete(PK id) {
Assert.notNull(id);
delete(get(id));
}
public List<T> findAll() {
return findByCriteria();
}
public Page<T> findAll(Page<T> page) {
return findByCriteria(page);
}
@SuppressWarnings("unchecked")
public List<T> find(String hql, Object... values) {
return (List<T>)createQuery(hql, values).list();
}
@SuppressWarnings("unchecked")
public List<T> findBySql(String sql, Object... values) {
return (List<T>)createSQLQuery(sql, values).addEntity(entityClass).list();
}
@SuppressWarnings("unchecked")
public Page<T> find(Page<T> page, String hql, Object... values) {
Assert.notNull(page);
if(page.isAutoCount()) {
page.setTotalCount(countQueryResult(hql, values));
}
Query q = createQuery(hql, values);
if(page.isFirstSetted()) {
q.setFirstResult(page.getFirst());
}
if(page.isPageSizeSetted()) {
q.setMaxResults(page.getPageSize());
}
page.setResult((List<T>)q.list());
return page;
}
@SuppressWarnings("unchecked")
public Page<T> findBySql(Page<T> page, String sql, Object... values) {
Assert.notNull(page);
if(page.isAutoCount()) {
page.setTotalCount(countSQLQueryResult(sql, values));
}
SQLQuery q = createSQLQuery(sql, values);
if(page.isFirstSetted()) {
q.setFirstResult(page.getFirst());
}
if(page.isPageSizeSetted()) {
q.setMaxResults(page.getPageSize());
}
page.setResult((List<T>)q.addEntity(entityClass).list());
return page;
}
public Object findUnique(String hql, Object... values) {
return createQuery(hql, values).uniqueResult();
}
public Object findUniqueBySql(String sql, Object... values) {
return createSQLQuery(sql, values).addEntity(entityClass).uniqueResult();
}
@SuppressWarnings("unchecked")
public List<T> findByCriteria(Criterion... criterion) {
return (List<T>)createCriteria(criterion).list();
}
@SuppressWarnings("unchecked")
public Page<T> findByCriteria(Page<T> page, Criterion... criterion) {
Assert.notNull(page);
Criteria c = createCriteria(criterion);
if(page.isAutoCount()) {
page.setTotalCount(countCriteriaResult(page, c));
}
if(page.isFirstSetted()) {
c.setFirstResult(page.getFirst());
}
if(page.isPageSizeSetted()) {
c.setMaxResults(page.getPageSize());
}
if(page.isOrderBySetted()) {
if(page.getOrder().toUpperCase().equals("AES")) {
c.addOrder(Order.asc(page.getOrderBy()));
} else {
c.addOrder(Order.desc(page.getOrderBy()));
}
}
page.setResult((List<T>)c.list());
return page;
}
@SuppressWarnings("unchecked")
public List<T> findByProperty(String propertyName, Object value) {
Assert.hasText(propertyName);
return (List<T>) createCriteria(Restrictions.eq(propertyName, value)).list();
}
@SuppressWarnings("unchecked")
public T findUniqueByProperty(String propertyName, Object value) {
Assert.hasText(propertyName);
return (T)createCriteria(Restrictions.eq(propertyName, value)).uniqueResult();
}
public boolean isPropertyUnique(String propertyName, Object newValue) {
if(newValue == null) return false;
try {
Object obj = findUniqueByProperty(propertyName, newValue);
return obj == null;
} catch (HibernateException e) {
return false;
}
}
public Query createQuery(String queryString, Object... values) {
Assert.hasText(queryString);
Query queryObject = sessionFactory.getCurrentSession().createQuery(queryString);
if(values != null) {
for(int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return queryObject;
}
public SQLQuery createSQLQuery(String queryString, Object... values) {
Assert.hasText(queryString);
SQLQuery queryObject = sessionFactory.getCurrentSession().createSQLQuery(queryString);
if(values != null) {
for(int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return queryObject;
}
public Criteria createCriteria(Criterion... criterions) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(entityClass);
for(Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}
public long countQueryResult(String hql, Object... values) {
hql = hql.replaceAll(" [Ff][Rr][Oo][Mm] ", " from ");
String str = hql.toLowerCase();
if(!StringUtils.contains(str, "group by")
&& !StringUtils.contains(str, "union")
&& !StringUtils.contains(str, "minus")
&& !StringUtils.contains(str, "intersect")
&& !StringUtils.contains(StringUtils.substringAfter(str, "from"), "(")
) {
str = "select count(*) from " + StringUtils.substringAfter(hql, "from");
return ((Number)createQuery(hql, values).iterate().next()).longValue();
} else {
throw new HibernateException("not support this HQL : " + hql);
}
}
public long countSQLQueryResult(String sql, Object... values) {
String str = sql.toLowerCase();
String beforeFrom = StringUtils.substringBefore(str, "from");
if(StringUtils.countMatches(beforeFrom, "(")
!= StringUtils.countMatches(beforeFrom, ")")
|| StringUtils.contains(str, "group by")
|| StringUtils.contains(str, "union")
|| StringUtils.contains(str, "minus")
|| StringUtils.contains(str, "intersect")) {
str = "select count(*) from (" + sql + ") as tmp";
} else {
str = "select count(*) from " +
StringUtils.substringAfter(str, "from");
}
Object ret = createSQLQuery(str, values).uniqueResult();
return (ret == null ? 0 : ((Number)ret).longValue());
}
@SuppressWarnings("unchecked")
public long countCriteriaResult(Page<T> page, Criteria c) {
CriteriaImpl cimpl = (CriteriaImpl)c;
// First Projection, ResultTransformer, OrderBy out ,Empty after a three Count operations
Projection projection = cimpl.getProjection();
ResultTransformer transformer = cimpl.getResultTransformer();
List<CriteriaImpl.OrderEntry> orderEntries = null;
try {
Field orderEntriesField = cimpl.getClass().getDeclaredField("orderEntries");
orderEntriesField.setAccessible(true);
orderEntries = (List<OrderEntry>) ReflectionUtils.getField(
orderEntriesField, cimpl);
ReflectionUtils.setField(
orderEntriesField, cimpl,
new ArrayList<OrderEntry>());
} catch (Exception e) {
logger.error("Not may throw an exception :{}", e.getMessage());
}
// Do Count query
long totalCount = (Long) c.setProjection(Projections.rowCount())
.uniqueResult();
if (totalCount < 1)
return -1;
// Will the Projection and OrderBy before conditions back to go back
c.setProjection(projection);
if (projection == null) {
c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
if (transformer != null) {
c.setResultTransformer(transformer);
}
try {
Field orderEntriesField = cimpl.getClass().getDeclaredField("orderEntries");
orderEntriesField.setAccessible(true);
ReflectionUtils.setField(orderEntriesField, cimpl, orderEntries);
} catch (Exception e) {
logger.error("Not may throw an exception :{}", e.getMessage());
}
return totalCount;
}
private int tuneBatchSize(int batchSize) {
if(batchSize < 20) {
batchSize = 20;
} else if(batchSize > 200) {
batchSize = 200;
}
return batchSize;
}
public int batchSave(List<T> entities, int batchSize) {
Assert.notEmpty(entities);
batchSize = tuneBatchSize(batchSize);
int count = 0;
Session session = sessionFactory.getCurrentSession();
for(int i = 0; i < entities.size(); i++) {
session.save(entities.get(i));
if(i % batchSize == 0 || i == entities.size() - 1) {
session.flush();
session.clear();
}
count++;
}
return count;
}
public int batchUpdate(List<T> entities, int batchSize) {
Assert.notEmpty(entities);
batchSize = tuneBatchSize(batchSize);
int count = 0;
Session session = sessionFactory.getCurrentSession();
for(int i = 0; i < entities.size(); i++) {
session.update(entities.get(i));
if(i % batchSize == 0 || i == entities.size() - 1) {
session.flush();
session.clear();
}
count++;
}
return count;
}
public int batchSaveOrUpdate(List<T> entities, int batchSize) {
Assert.notEmpty(entities);
batchSize = tuneBatchSize(batchSize);
int count = 0;
Session session = sessionFactory.getCurrentSession();
for(int i = 0; i < entities.size(); i++) {
session.saveOrUpdate(entities.get(i));
if(i % batchSize == 0 || i == entities.size() - 1) {
session.flush();
session.clear();
}
count++;
}
return count;
}
public int batchUpdateSelective(List<T> entities, int batchSize) {
Assert.notEmpty(entities);
batchSize = tuneBatchSize(batchSize);
int count = 0;
Session session = sessionFactory.getCurrentSession();
for(int i = 0; i < entities.size(); i++) {
updateSelective(entities.get(i));
if(i % batchSize == 0 || i == entities.size() - 1) {
session.flush();
session.clear();
}
count++;
}
return count;
}
public int batchMerge(List<T> entities, int batchSize) {
Assert.notEmpty(entities);
batchSize = tuneBatchSize(batchSize);
int count = 0;
Session session = sessionFactory.getCurrentSession();
for(int i = 0; i < entities.size(); i++) {
session.merge(entities.get(i));
if(i % batchSize == 0 || i == entities.size() - 1) {
session.flush();
session.clear();
}
count++;
}
return count;
}
public int batchDelete(List<T> entities, int batchSize) {
Assert.notEmpty(entities);
batchSize = tuneBatchSize(batchSize);
int count = 0;
Session session = sessionFactory.getCurrentSession();
for(int i = 0; i < entities.size(); i++) {
session.delete(entities.get(i));
if(i % batchSize == 0 || i == entities.size() - 1) {
session.flush();
session.clear();
}
count++;
}
return count;
}
}