一个泛型Hibernate DAO,用了Spring的HibernateDaoSupport。提供基本的CRUD操作,支持分页查询,可使用HQL、Criteria和DetachedCriteria.
package sgf4web.dao; import java.io.Serializable; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.hibernate.*; import org.hibernate.criterion.*; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import sgf4web.dao.support.PaginationSupport; import sgf4web.util.GenericsUtils; /** * 泛型Hibernate DAO类 * * @author DigitalSonic */ @SuppressWarnings("unchecked") public class HibernateGenericDao<T, ID extends Serializable> extends HibernateDaoSupport { private Class<T> pojoClass; /** * 初始化DAO,获取POJO类型 */ public HibernateGenericDao() { // this.pojoClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; this.pojoClass = GenericsUtils.getSuperClassGenricType(getClass()); } /** * 获得该DAO对应的POJO类型 */ public Class<T> getPojoClass() { return this.pojoClass; } /** * 获得该DAO对应的POJO类型名 */ public String getPojoClassName() { return getPojoClass().getName(); } //加载对象 /** * 加载所有的对象 */ public List<T> loadAll() { return (List<T>)getHibernateTemplate().loadAll(getPojoClass()); } /** * 根据hql查询 * * @param values 可变参数 */ public List find(String hql, Object... values) { return getHibernateTemplate().find(hql, values); } /** * 根据条件加载对象 * * @param criteria Criteria实例 */ public List<T> findByCriteria(final Criteria criteria) { List list = criteria.list(); return transformResults(list); } /** * 根据条件加载对象 * @param detachedCriteria DetachedCriteria实例 */ public List<T> findByCriteria(final DetachedCriteria detachedCriteria) { return (List<T>) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); List list = criteria.list(); return transformResults(list); } }, true); } /** * 根据给定的实例查找对象 */ public List<T> findByExample(T instance) { List<T> results = (List<T>)getHibernateTemplate().findByExample(instance); return results; } /** * 根据ID查找对象 */ public T findById(ID id) { return (T) getHibernateTemplate().get(getPojoClassName(), id); } /** * 根据某个具体属性进行查找 */ public List<T> findByProperty(String propertyName, Object value) { String queryString = "from " + getPojoClassName() + " as model where model." + propertyName + "= ?"; return (List<T>)getHibernateTemplate().find(queryString, value); } //新建、修改、删除 /** * 新建对象实例化 */ public ID save(T transientInstance) { return (ID)getHibernateTemplate().save(transientInstance); } /** * 更新已存在的对象 */ public void update(T transientInstance) { getHibernateTemplate().update(transientInstance); } /** * 删除指定ID的对象 */ public void delete(ID id) { T instance = findById(id); if (instance != null) getHibernateTemplate().delete(instance); } /** * 删除指定对象 */ public void delete(T persistentInstance) { getHibernateTemplate().delete(persistentInstance); } //分页 /** * 根据Criteria加载分页,指定页大小和起始位置 */ public PaginationSupport findPageByCriteria(final Criteria criteria, final int pageSize, final int startIndex) { int totalCount = getCountByCriteria(criteria); criteria.setProjection(null); List items = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list(); items = transformResults(items); PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex); return ps; } /** * 根据Criteria加载分页,默认页大小,从第0条开始 */ public PaginationSupport findPageByCriteria(final Criteria criteria) { return findPageByCriteria(criteria, PaginationSupport.PAGESIZE, 0); } /** * 根据Criteria加载分页,默认页大小,从第startIndex条开始 */ public PaginationSupport findPageByCriteria(final Criteria criteria, final int startIndex) { return findPageByCriteria(criteria, PaginationSupport.PAGESIZE, startIndex); } /** * 根据Criteria统计总数 */ public int getCountByCriteria(final Criteria criteria) { Integer count = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult(); return count.intValue(); } /** * 根据DetachedCriteria加载分页,指定页大小和起始位置 */ public PaginationSupport findPageByCriteria(final DetachedCriteria detachedCriteria, final int pageSize, final int startIndex) { return (PaginationSupport) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue(); criteria.setProjection(null); List items = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list(); items = transformResults(items); PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex); return ps; } }, true); } /** * 根据DetachedCriteria加载分页,默认页大小,从第0条开始 */ public PaginationSupport findPageByCriteria(final DetachedCriteria detachedCriteria) { return findPageByCriteria(detachedCriteria, PaginationSupport.PAGESIZE, 0); } /** * 根据DetachedCriteria加载分页,默认页大小,从第startIndex条开始 */ public PaginationSupport findPageByCriteria(final DetachedCriteria detachedCriteria, final int startIndex) { return findPageByCriteria(detachedCriteria, PaginationSupport.PAGESIZE, startIndex); } /** * 根据DetachedCriteria统计总数 */ public int getCountByCriteria(final DetachedCriteria detachedCriteria) { Integer count = (Integer) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); return criteria.setProjection(Projections.rowCount()).uniqueResult(); } }, true); return count.intValue(); } /** * 根据hql加载分页,指定页大小和起始位置 */ public PaginationSupport findPageByQuery(final String hql, final int pageSize, final int startIndex, Object...values) { int totalCount = getCountByQuery(hql, values); if (totalCount < 1) return new PaginationSupport(new ArrayList(0), 0); Query query = createQuery(hql, values); List items = query.setFirstResult(startIndex).setMaxResults(pageSize).list(); PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex); return ps; } /** * 根据hql加载分页,默认页大小,从第0条开始 */ public PaginationSupport findPageByQuery(final String hql, Object...values) { return findPageByQuery(hql, PaginationSupport.PAGESIZE, 0, values); } /** * 根据hql加载分页,默认页大小,从第startIndex条开始 */ public PaginationSupport findPageByQuery(final String hql, final int startIndex, Object...values) { return findPageByQuery(hql, PaginationSupport.PAGESIZE, startIndex, values); } /** * 根据hql统计总数 */ public int getCountByQuery(final String hql, Object...values) { String countQueryString = " select count (*) " + removeSelect(removeOrders(hql)); List countlist = getHibernateTemplate().find(countQueryString, values); return (Integer) countlist.get(0); } //创建Criteria和Query /** * 创建Criteria对象 * * @param criterions 可变的Restrictions条件列表 */ public Criteria createCriteria(Criterion...criterions) { Criteria criteria = getSession().createCriteria(getPojoClass()); for (Criterion c : criterions) criteria.add(c); return criteria; } /** * 创建Criteria对象,带排序字段与升降序字段 */ public Criteria createCriteria(String orderBy, boolean isAsc, Criterion...criterions) { Criteria criteria = createCriteria(criterions); if (isAsc) criteria.addOrder(Order.asc(orderBy)); else criteria.addOrder(Order.desc(orderBy)); return criteria; } /** * 方法取自SpringSide. * 创建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) { Query query = getSession().createQuery(hql); for (int i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } return query; } /** * 方法取自SpringSide. * 去除hql的select子句,未考虑union的情况 */ private static String removeSelect(String hql) { int beginPos = hql.toLowerCase().indexOf("from"); return hql.substring(beginPos); } /** * 方法取自SpringSide. * 去除hql的orderby子句 */ private static String removeOrders(String 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(); } /** * 将联合查询的结果内容从Map或者Object[]转换为实体类型,如果没有转换必要则直接返回 */ private List transformResults(List items) { if (items.size() > 0) { if (items.get(0) instanceof Map) { ArrayList list = new ArrayList(items.size()); for (int i = 0; i < items.size(); i++) { Map map = (Map)items.get(i); list.add(map.get(CriteriaSpecification.ROOT_ALIAS)); } return list; } else if (items.get(0) instanceof Object[]) { ArrayList list = new ArrayList(items.size()); int pos = 0; for (int i = 0; i < ((Object[])items.get(0)).length; i++) { if (((Object[])items.get(0))[i].getClass() == getPojoClass()) { pos = i; break; } } for (int i = 0; i < items.size(); i++) { list.add(((Object[])items.get(i))[pos]); } return list; } else return items; } else return items; } }
package sgf4web.util; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; /** * 泛型参数辅助类 * * @author DigitalSonic */ @SuppressWarnings("unchecked") public class GenericsUtils { /** * 通过反射,获得定义Class时声明的父类的第一个范型参数的类型。 */ public static Class getSuperClassGenricType(Class clazz) { return getSuperClassGenricType(clazz, 0); } /** * 通过反射,获得定义Class时声明的父类的范型参数的类型。 * 如没有找到符合要求的范型参数,则递归向上直到Object。 * * @param clazz 要进行查询的类 * @param index 如有多个范型声明该索引从0开始 * @return 在index位置的范型参数的类型,如果无法判断则返回<code>Object.class</code> */ public static Class getSuperClassGenricType(Class clazz, int index) { boolean flag = true; Type genType = clazz.getGenericSuperclass(); Type[] params = null; if (!(genType instanceof ParameterizedType)) flag = false; else { params = ((ParameterizedType) genType).getActualTypeArguments(); if (index >= params.length || index < 0) flag = false; if (!(params[index] instanceof Class)) flag = false; } if (!flag) { clazz = clazz.getSuperclass(); if (clazz == Object.class) return Object.class; else return getSuperClassGenricType(clazz, index); } return (Class) params[index]; } }
package sgf4web.dao.support; import java.util.List; /** * 分页类,参考自JavaEye及SpringSide */ @SuppressWarnings("unchecked") public class PaginationSupport { public final static int PAGESIZE = 10; private int pageSize = PAGESIZE; private List items; private int totalCount; private int[] indexes = new int[0]; private int startIndex = 0; public PaginationSupport(List items, int totalCount) { setPageSize(PAGESIZE); setTotalCount(totalCount); setItems(items); setStartIndex(0); } public PaginationSupport(List items, int totalCount, int startIndex) { setPageSize(PAGESIZE); setTotalCount(totalCount); setItems(items); setStartIndex(startIndex); } public PaginationSupport(List items, int totalCount, int pageSize, int startIndex) { setPageSize(pageSize); setTotalCount(totalCount); setItems(items); setStartIndex(startIndex); } /** * 将页码转换为列表的startIndex,页大小为默认大小 */ public static int convertFromPageToStartIndex(int pageNo) { return (pageNo - 1) * PAGESIZE; } /** * 将页码转换为列表的startIndex */ public static int convertFromPageToStartIndex(int pageNo, int pageSize) { return (pageNo - 1) * pageSize; } public List getItems() { return items; } public void setItems(List items) { this.items = items; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalCount() { return totalCount; } /** * 设置数据总数,并计算各页起始位置 */ public void setTotalCount(int totalCount) { if (totalCount > 0) { this.totalCount = totalCount; int count = totalCount / pageSize; if (totalCount % pageSize > 0) count++; indexes = new int[count]; for (int i = 0; i < count; i++) { indexes[i] = pageSize * i; } } else { this.totalCount = 0; } } public int[] getIndexes() { return indexes; } public void setIndexes(int[] indexes) { this.indexes = indexes; } public int getStartIndex() { return startIndex; } /** * 设置当前起始位置 */ public void setStartIndex(int startIndex) { if (totalCount <= 0) this.startIndex = 0; else if (startIndex >= totalCount) this.startIndex = indexes[indexes.length - 1]; else if (startIndex < 0) this.startIndex = 0; else { this.startIndex = indexes[startIndex / pageSize]; } } /** * 获得下页起始位置 */ public int getNextIndex() { int nextIndex = getStartIndex() + pageSize; if (nextIndex >= totalCount) return getStartIndex(); else return nextIndex; } /** * 获得上页起始位置 */ public int getPreviousIndex() { int previousIndex = getStartIndex() - pageSize; if (previousIndex < 0) return 0; else return previousIndex; } /** * 取总页数. */ public long getTotalPageCount() { if (totalCount % pageSize == 0) return totalCount / pageSize; else return totalCount / pageSize + 1; } /** * 取该页当前页码,页码从1开始. */ public long getCurrentPageNo() { return startIndex / pageSize + 1; } /** * 该页是否有下一页. */ public boolean hasNextPage() { return this.getCurrentPageNo() < this.getTotalPageCount() - 1; } /** * 该页是否有上一页. */ public boolean hasPreviousPage() { return this.getCurrentPageNo() > 1; } }