hibernate 基礎dao類實現

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
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.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

import com.framework.commons.pagination.Page;
import com.framework.commons.utils.BeanUtils;

/**
 * Hibernate Dao的泛型基 <p/> 繼承於Spring<code>HibernateDaoSupport</code>,提供分頁函數和若干便捷查詢方法,並對返回值作了泛型類型轉
 *
 * @author calvin
 * @author tin
 * @see HibernateDaoSupport
 * @see HibernateEntityDao
 */
@SuppressWarnings("unchecked")
public class HibernateGenericDao extends HibernateDaoSupport {
 /**
  * 根據ID獲取對象. 實際調用Hibernate的session.load()方法返回實體或其proxy對象. 如果對象不存在,拋出異常.
  */
 public <T> T findById(Class<T> entityClass, Serializable id) {
  return (T) getHibernateTemplate().load(entityClass, id);
 }

 /**
  * 獲取全部對象.
  */
 public <T> List<T> findAll(Class<T> entityClass) {
  return getHibernateTemplate().loadAll(entityClass);
 }

 /**
  * 獲取全部對象,帶排序字段與升降序參
  */
 public <T> List<T> findAll(Class<T> entityClass, String orderBy,
   boolean isAsc) {
  Assert.hasText(orderBy);
  if (isAsc)
   return getHibernateTemplate().findByCriteria(
     DetachedCriteria.forClass(entityClass).addOrder(
       Order.asc(orderBy)));
  else
   return getHibernateTemplate().findByCriteria(
     DetachedCriteria.forClass(entityClass).addOrder(
       Order.desc(orderBy)));
 }

 /**
  * 保存對象.
  */
 public Serializable create(Object o) {
  return getHibernateTemplate().save(o);
 }
 
 /**
  * 保存對象.
  */
 public void update(Object o) {
  getHibernateTemplate().update(o);
 }

 /**
  * 刪除對象.
  */
 public void delete(Object o) {
  getHibernateTemplate().delete(o);
 }


 public void flush() {
  getHibernateTemplate().flush();
 }

 public void clear() {
  getHibernateTemplate().clear();
 }

 /**
  * 創建Query對象.
  * 對於要first,max,fetchsize,cache,cacheRegion等諸多設置的函數,可以在返回Query後自行設
  * 留意可以連續設置,如下
  *
  * <pre>
  * dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
  * </pre>
  *
  * 調用方式如下
  *
  * <pre>
  *        dao.createQuery(hql)
  *        dao.createQuery(hql,arg0);
  *        dao.createQuery(hql,arg0,arg1);
  *        dao.createQuery(hql,new Object[arg0,arg1,arg2])
  * </pre>
  *
  * @param values
  *            可變參數.
  */
 public Query createQuery(String hql, Object... values) {
  Assert.hasText(hql);
  Query query = getSession().createQuery(hql);
  for (int i = 0; i < values.length; i++) {
   query.setParameter(i, values[i]);
  }
  return query;
 }

 /**
  * 創建Query對象.防止注入
  * @param hql 查詢語句
  * @param values list集合
  * @return
  */
 public Query createQuery(String hql, List<Object> values) {
  Assert.hasText(hql);
  Query query = getSession().createQuery(hql);
  if(values!=null)
  {
  for (int i = 0; i < values.size(); i++) {
   query.setParameter(i, values.get(i));
  }
  }
  return query;
 }
 
 
 
 /**
  * 創建Query對象.防止注入
  * @param hql 查詢語句
  * @param values list集合
  * @return
  */
 public Query createSQLQuery(String hql, List<Object> values) {
  Assert.hasText(hql);
  Query query = getSession().createSQLQuery(hql);
  if (values != null) {
   for (int i = 0; i < values.size(); i++) {
    query.setParameter(i, values.get(i));
   }
  }
  return query;
 }

 /**
  * 創建Criteria對象.
  *
  * @param criterions
  *            可變的Restrictions條件列表,見{@link #createQuery(String,Object...)}
  */
 public <T> Criteria createCriteria(Class<T> entityClass,
   Criterion... criterions) {
  Criteria criteria = getSession().createCriteria(entityClass);
  for (Criterion c : criterions) {
   criteria.add(c);
  }
  return criteria;
 }

 /**
  * 創建Criteria對象,帶排序字段與升降序字段.
  *
  * @see #createCriteria(Class,Criterion[])
  */
 public <T> Criteria createCriteria(Class<T> entityClass, String orderBy,
   boolean isAsc, Criterion... criterions) {
  Assert.hasText(orderBy);

  Criteria criteria = createCriteria(entityClass, criterions);

  if (isAsc)
   criteria.addOrder(Order.asc(orderBy));
  else
   criteria.addOrder(Order.desc(orderBy));

  return criteria;
 }

 /**
  * 根據hql查詢,直接使用HibernateTemplate的find函數.
  *
  * @param values
  *            可變參數,見{@link #createQuery(String,Object...)}
  */
 public List find(String hql, Object... values) {
  Assert.hasText(hql);
  return getHibernateTemplate().find(hql, values);
 }

 /**
  * 根據屬名和屬性查詢對
  *
  * @return 符合條件的對象列
  */
 public <T> List<T> findBy(Class<T> entityClass, String propertyName,
   Object value) {
  Assert.hasText(propertyName);
  return createCriteria(entityClass, Restrictions.eq(propertyName, value))
    .list();
 }

 /**
  * 根據屬名和屬性查詢對,帶排序參
  */
 public <T> List<T> findBy(Class<T> entityClass, String propertyName,
   Object value, String orderBy, boolean isAsc) {
  Assert.hasText(propertyName);
  Assert.hasText(orderBy);
  return createCriteria(entityClass, orderBy, isAsc,
    Restrictions.eq(propertyName, value)).list();
 }

 /**
  * 根據屬名和屬性查詢唯對象.
  *
  * @return 符合條件的唯對象 or null if not found.
  */
 public <T> T findUniqueBy(Class<T> entityClass, String propertyName,
   Object value) {
  Assert.hasText(propertyName);
  return (T) createCriteria(entityClass,
    Restrictions.eq(propertyName, value)).uniqueResult();
 }

 /**
  * 分頁查詢函數,使用hql.
  *
  * @param pageNo
  *            頁號
  */
 public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
  Assert.hasText(hql);
  Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
  // Count查詢
  String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
  List countlist = getHibernateTemplate().find(countQueryString, values);
  long totalCount = (Long) countlist.get(0);

  if (totalCount < 1)
   return new Page();
  // 實際查詢返回分頁對象
  int startIndex = Page.getStartOfPage(pageNo, pageSize);
  Query query = createQuery(hql, values);
  List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
       
  return new Page(pageNo, totalCount, pageSize, list);
 }

 /**
  * 分頁查詢函數,使用已設好查詢條件與排序的<code>Criteria</code>.
  *
  * @param pageNo
  *            頁號
  * @return 含記錄數和當前頁數據的Page對象.
  */
 public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
  Assert.notNull(criteria);
  Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
  CriteriaImpl impl = (CriteriaImpl) criteria;

  Projection projection = impl.getProjection();
  List<CriteriaImpl.OrderEntry> orderEntries;
  try {
   orderEntries = (List) BeanUtils.forceGetProperty(impl,
     "orderEntries");
   BeanUtils.forceSetProperty(impl, "orderEntries", new ArrayList());
  } catch (Exception e) {
   throw new InternalError(" Runtime Exception impossibility throw ");
  }

  // 執行查詢
  long totalCount = (Long) criteria.setProjection(Projections.rowCount())
    .uniqueResult();

  // 將之前的Projection和OrderBy條件重新設回
  criteria.setProjection(projection);
  if (projection == null) {
   criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
  }

  try {
   BeanUtils.forceSetProperty(impl, "orderEntries", orderEntries);
  } catch (Exception e) {
   throw new InternalError(" Runtime Exception impossibility throw ");
  }

  // 返回分頁對象
  if (totalCount < 1)
   return new Page();

  int startIndex = Page.getStartOfPage(pageNo, pageSize);
  List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize)
    .list();
  return new Page(startIndex, totalCount, pageSize, list);
 }

 /**
  * 分頁查詢函數,根據entityClass和查詢條件參數創建默認的<code>Criteria</code>.
  *
  * @param pageNo
  *            頁號
  * @return 含記錄數和當前頁數據的Page對象.
  */
 public Page pagedQuery(Class entityClass, int pageNo, int pageSize,
   Criterion... criterions) {
  Criteria criteria = createCriteria(entityClass, criterions);
  return pagedQuery(criteria, pageNo, pageSize);
 }

 /**
  * 分頁查詢函數,根據entityClass和查詢條件參,排序參數創建默認<code>Criteria</code>.
  *
  * @param pageNo
  *            頁號
  * @return 含記錄數和當前頁數據的Page對象.
  */
 public Page pagedQuery(Class entityClass, int pageNo, int pageSize,
   String orderBy, boolean isAsc, Criterion... criterions) {
  Criteria criteria = createCriteria(entityClass, orderBy, isAsc,
    criterions);
  return pagedQuery(criteria, pageNo, pageSize);
 }

 /**
  * 判斷對象某些屬的值在數據庫中是否唯一.
  *
  * @param uniquePropertyNames
  *            在POJO裏不能重複的屬列,以號分割"name,loginid,password"
  */
 public <T> boolean isUnique(Class<T> entityClass, Object entity,
   String uniquePropertyNames) {
  Assert.hasText(uniquePropertyNames);
  Criteria criteria = createCriteria(entityClass).setProjection(
    Projections.rowCount());
  String[] nameList = uniquePropertyNames.split(",");
  try {
   // 循環加入唯一
   for (String name : nameList) {
    criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(
      entity, name)));
   }

   // 以下代碼爲了如果是update的情,排除entity自身.

   String idName = getIdName(entityClass);

   // 取得entity的主鍵
   Serializable id = getId(entityClass, entity);

   // 如果id!=null,說明對象已存,該操作爲update,加入排除自身的判
   if (id != null)
    criteria.add(Restrictions.not(Restrictions.eq(idName, id)));
  } catch (Exception e) {
   ReflectionUtils.handleReflectionException(e);
  }
  return (Integer) criteria.uniqueResult() == 0;
 }

 /**
  * 取得對象的主鍵,輔助函數.
  */
 public Serializable getId(Class entityClass, Object entity)
   throws NoSuchMethodException, IllegalAccessException,
   InvocationTargetException {
  Assert.notNull(entity);
  Assert.notNull(entityClass);
  return (Serializable) PropertyUtils.getProperty(entity,
    getIdName(entityClass));
 }

 /**
  * 取得對象的主鍵名,輔助函數.
  */
 public String getIdName(Class clazz) {
  Assert.notNull(clazz);
  ClassMetadata meta = getSessionFactory().getClassMetadata(clazz);
  Assert.notNull(meta, "Class " + clazz
    + " not define in hibernate session factory.");
  String idName = meta.getIdentifierPropertyName();
  Assert.hasText(idName, clazz.getSimpleName()
    + " has no identifier property define.");
  return idName;
 }

 /**
  * 去除hql的select 子句,未考慮union的情,用於pagedQuery.
  *
  * @see #pagedQuery(String,int,int,Object[])
  */
 public static String removeSelect(String hql) {
  Assert.hasText(hql);
  int beginPos = hql.toLowerCase().indexOf("from");
  Assert.isTrue(beginPos != -1, " hql : " + hql
    + " must has a keyword 'from'");
  return hql.substring(beginPos);
 }

 /**
  * 去除hql的orderby 子句,用於pagedQuery.
  *
  * @see #pagedQuery(String,int,int,Object[])
  */
 public  static String removeOrders(String hql) {
  Assert.hasText(hql);
  Pattern p = Pattern.compile("order//s*by[//w|//W|//s|//S]*",
    Pattern.CASE_INSENSITIVE);
  Matcher m = p.matcher(hql);
  StringBuffer sb = new StringBuffer();
  while (m.find()) {
   m.appendReplacement(sb, "");
  }
  m.appendTail(sb);
  return sb.toString();
 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章