Hibernate 泛型DAO实现代码


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

}


你可能感兴趣的:(DAO,Hibernate)