/** * Copyright (c) http://www.hao-se.cn Ltd.,2007 All rights reserved. */ package com.joe.utilities.core.hibernate.entrydao.impl; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Query; import org.hibernate.criterion.DetachedCriteria; import org.springframework.orm.ObjectRetrievalFailureException; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.util.Assert; import com.joe.utilities.core.data.PageRequest; import com.joe.utilities.core.data.PageResponse; import com.joe.utilities.core.hibernate.entrydao.GenericDAO; /** * 泛型DAO父类 * * * DAO异常处理原则: DAO 方法应该抛出有意义的异常。 DAO 方法不应该抛出 java.lang.Exception。<br> * java.lang.Exception 太一般化了。它不传递关于底层问题的任何信息。 DAO 方法不应该抛出 java.sql.SQLException 。<br> * SQLException 是一个低级别的 JDBC 异常。 一个 DAO 应该力争封装 JDBC 而不是将 JDBC公开给应用程序的其余部分。<br> * 只有在可以合理地预期调用者可以处理异常时,DAO 接口中的方法才应该抛出检查过的异常。<br> * 如果调用者不能以有意义的方式处理这个异常,那么考虑抛出一个未检查的(运行时)异常。 <br> * 如果数据访问代码捕获了一个异常,不要忽略它。 忽略捕获的异常的DAO是很难进行故障诊断的。 <br> * 使用链接的异常将低级别的异常转化为高级别的异常。 考虑定义标准DAO异常类。 <br> * Spring Framework提供了很好的一套预定义的 DAO 异常类 * * @author hao-se.cn(好·色) */ @SuppressWarnings("unchecked") public class BaseGenericDAO<T> extends HibernateDaoSupport implements GenericDAO<T> { /** 日志 */ protected final Log log = LogFactory.getLog(getClass()); /** 型别 */ protected Class<T> type; /** * 提供给spring初始化的构造函数 */ public BaseGenericDAO() { super(); } /** * 用于初始化对应model的构造函数 * * @param type */ public BaseGenericDAO(Class<T> type) { super(); this.type = type; } protected String getDefalutOrderFileds() { return null; } /* * @see cn.haose.dao.GenericDAO#saveEntity(java.lang.Object) */ public void saveEntity(T o) { getHibernateTemplate().saveOrUpdate(o); } /* * @see cn.haose.dao.GenericDAO#deleteEntity(java.lang.Object) */ public void deleteEntity(T o) { getHibernateTemplate().delete(o); } /* * @see cn.haose.dao.GenericDAO#getByID(java.lang.String) */ public T getByID(String id) { Object o = this.getHibernateTemplate().get(type, id); if (o == null) { throw new ObjectRetrievalFailureException(type, id); } return (T) o; } /* * @see cn.haose.dao.GenericDAO#getByID(java.lang.String) */ public T getByID(Long id) { Object o = this.getHibernateTemplate().get(type, id); if (o == null) { throw new ObjectRetrievalFailureException(type, id); } return (T) o; } /* * @see cn.haose.dao.GenericDAO#findByDetachedCriteria(org.hibernate.criterion.DetachedCriteria) */ public List findByDetachedCriteria(final DetachedCriteria dc) { return getHibernateTemplate().findByCriteria(dc); } public List<T> findByProperty(String propertyName, Object value) { if (value != null) { String queryString = "from " + getClass().getName() + " as model where model." + propertyName + "= ?"; return getHibernateTemplate().find(queryString, value); } else { String queryString = "from " + getClass().getName() + " as model where model." + propertyName + " is null"; return getHibernateTemplate().find(queryString); } } public PageResponse<T> findByProperty1(String propertyName, Object value, PageRequest pageRequest) { PageResponse<T> pageResponse = new PageResponse<T>(); if (value != null) { String queryString = "from " + getClass().getName() + " as model where model." + propertyName + "= :value"; Query query = getSession().createQuery(queryString); query.setEntity("value", value); // 取总数 Long totalCount = getHQLReulstCount(queryString); pageResponse.setTotalCount(totalCount); query.setFirstResult(pageRequest.getStart()); query.setMaxResults(pageRequest.getLimit()); pageResponse.setList(query.list()); pageResponse.setStart(pageRequest.getStart() + 1); pageResponse.setEnd(pageResponse.getStart()+pageResponse.getList().size() - 1); return pageResponse; } else { String queryString = "from " + getClass().getName() + " as model where model." + propertyName + " is null"; Query query = getSession().createQuery(queryString); // 取总数 Long count = getHQLReulstCount(queryString.toString()); pageResponse.setTotalCount(count); query.setFirstResult(pageRequest.getStart()); query.setMaxResults(pageRequest.getLimit()); pageResponse.setList(query.list()); pageResponse.setStart(pageRequest.getStart() + 1); pageResponse.setEnd(pageResponse.getStart()+pageResponse.getList().size() - 1); return pageResponse; } } public PageResponse<T> findAll(PageRequest pageRequest) { PageResponse<T> pageResponse = new PageResponse<T>(); StringBuffer hql = new StringBuffer(); hql.append(" FROM ").append(getClass().getSimpleName()); String defalutOrderFileds = getDefalutOrderFileds(); if (StringUtils.isNotEmpty(defalutOrderFileds)) { hql.append(" order by " + defalutOrderFileds); } String queryString = hql.toString(); Query query = getSession().createQuery(queryString); // 取总数 Long count = getHQLReulstCount(hql.toString()); pageResponse.setTotalCount(count); // 取结果 query.setFirstResult(pageRequest.getStart()); query.setMaxResults(pageRequest.getLimit()); pageResponse.setList(query.list()); pageResponse.setStart(pageRequest.getStart() + 1); pageResponse.setEnd(pageResponse.getStart()+pageResponse.getList().size() - 1); return pageResponse; } public List<T> findAll() { StringBuffer hql = new StringBuffer(); hql.append(" FROM ").append(getClass().getName()); String defalutOrderFileds = getDefalutOrderFileds(); if (StringUtils.isNotEmpty(defalutOrderFileds)) { hql.append(" order by " + defalutOrderFileds); } String queryString = hql.toString(); return getHibernateTemplate().find(queryString); } /** * 返回给定HQL语句的记录总条数 * * @param hql * @return */ protected Long getHQLReulstCount(String hql) { String countSql = removeSelect(hql); countSql = removeOrders(countSql); countSql = removeFetchKeyword(countSql); countSql = " select count(*) " + countSql; Query query = getSession().createQuery(countSql); Long count = (Long) query.uniqueResult(); return count; } /** * 返回给定SQL语句的记录总条数 * * @param hql * @return */ protected Long getSQLReulstCount(String hql) { String countSql = removeSelect(hql); countSql = removeOrders(countSql); countSql = removeFetchKeyword(countSql); countSql = " select count(*) " + countSql; Query query = getSession().createSQLQuery(countSql); Long count = (Long) query.uniqueResult(); return count; } /** * 去除select 子句,未考虑union的情况 * * @param hql * @return */ private 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); } /** * 去除orderby 子句 * * @param hql * @return */ private 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(); } private static String removeFetchKeyword(String hql) { return hql.replaceAll("(?i)fetch", ""); } }