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; } }