可能是考虑适用性和作者的习惯,SpringSide没有基于Spring提供的HibernateDaoSupport,没有用HibernateTemplate实现,而是直接操作Hibernate,大量使用Criteria构建查询,这和我的习惯有很大不同。本着简单实用快速的原则,参照spring边上的思路,自己实现了下面这个泛型DAO,实现了基本的CRUD,hql查询,分页等功能,基本满足日常需要。 HibernateDao.java [java] view plaincopyprint? 1.package jj.utils; 2. 3.import java.io.Serializable; 4.import java.sql.SQLException; 5.import java.util.List; 6.import java.util.regex.Matcher; 7.import java.util.regex.Pattern; 8. 9.import org.hibernate.HibernateException; 10.import org.hibernate.Query; 11.import org.hibernate.Session; 12.import org.hibernate.SessionFactory; 13.import org.hibernate.metadata.ClassMetadata; 14.import org.slf4j.Logger; 15.import org.slf4j.LoggerFactory; 16.import org.springframework.beans.factory.annotation.Autowired; 17.import org.springframework.orm.hibernate3.HibernateCallback; 18.import org.springframework.orm.hibernate3.support.HibernateDaoSupport; 19. 20./** 21. * 泛型HibernateDAO基类, 参照SpringSide4 22. * 23. * @param<T> DAO操作的对象类型 24. * 25. * @author jj 26. * @version 0.1 27. */ 28.public abstract class HibernateDao<T> extends HibernateDaoSupport { 29.protected Logger log = LoggerFactory.getLogger(getClass()); 30.protected Class<T> entityClass; 31. 32.// 通过子类的泛型定义设置实体对象类型 33.public HibernateDao() { 34.this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass()); 35. } 36. 37.// 通过构造函数设置实体对象类型 38.public HibernateDao(Class<T> entityClass) { 39.this.entityClass = entityClass; 40. } 41. 42.// 自动注入SessionFactory 43.@Autowired 44.public void setupSessionFactory(final SessionFactory sessionFactory) { 45.this.setSessionFactory(sessionFactory); 46. } 47. 48.// 保存新增或修改的对象 49.public void save(final T entity) { 50. AssertUtils.notNull(entity, "entity不能为空"); 51.getHibernateTemplate().save(entity); 52. log.debug("save entity: {}", entity); 53. } 54. 55.// 删除对象 56.public void delete(final T entity) { 57. AssertUtils.notNull(entity, "entity不能为空"); 58.getHibernateTemplate().delete(entity); 59. log.debug("delete entity: {}", entity); 60. } 61. 62.// 按id删除对象 63.public void delete(Serializable id) { 64. AssertUtils.notNull(id, "id不能为空"); 65.delete(getById(id)); 66. log.debug("delete entity {},id is {}", entityClass.getSimpleName(), id); 67. } 68. 69.// 按id获取对象 70.public T getById(final Serializable id) { 71. AssertUtils.notNull(id, "id不能为空"); 72.return (T) getHibernateTemplate().get(entityClass, id); 73. } 74. 75.// 获取全部对象列表 76.public List<T> getAll() { 77.return getHibernateTemplate().find(prepareSelectHql()); 78. } 79. 80.// 查询对象列表 81.public <X> List<X> query(final String hql, final Object... values) { 82.return getHibernateTemplate().find(hql, values); 83. } 84. 85.// 条件查询对象列表 86.public List<T> queryWhere(final String where, final Object... values) { 87.return getHibernateTemplate().find(prepareWhereHql(where), values); 88. } 89. 90.// 分页查询对象列表 91.public <X> PageResult<X> queryPage(final int offset, final int length, final String hql, final Object... values) { 92. List list = getHibernateTemplate().executeFind(new HibernateCallback() { 93.public Object doInHibernate(Session session) throws HibernateException, SQLException { 94. Query query = createQuery(session, hql, values); 95. query.setFirstResult(offset); 96. query.setMaxResults(length); 97. List list = query.list(); 98.return list; 99. } 100. }); 101. PageResult res = new PageResult(); 102. res.setOffset(offset); 103. res.setLength(list.size()); 104. res.setTotal(getCount(hql, values)); 105. res.setResult(list); 106.return res; 107. } 108. 109.// 分页条件查询对象列表 110.public PageResult<T> queryPageWhere(final int offset, final int length, final String where, final Object... values) { 111.return queryPage(offset, length, prepareWhereHql(where), values); 112. } 113. 114.// 分页查询所有对象列表 115.public PageResult<T> queryPageAll(final int offset, final int length) { 116.return queryPage(offset, length, prepareSelectHql()); 117. } 118. 119.// 执行count查询获得本次Hql查询所能获得的对象总数 120.public long getCount(final String hql, final Object... values) { 121.return getHibernateTemplate().execute(new HibernateCallback<Long>() { 122.public Long doInHibernate(Session session) throws HibernateException, SQLException { 123.return (Long) createQuery(session, prepareCountHql(hql), values).uniqueResult(); 124. } 125. }); 126. } 127.// 批量执行 128.public int batchExecute(final String hql, final Object... values) { 129.return getHibernateTemplate().execute(new HibernateCallback<Integer>() { 130.public Integer doInHibernate(Session session) throws HibernateException, SQLException { 131.return (Integer) createQuery(session, hql, values).executeUpdate(); 132. } 133. }); 134. } 135.// 判断属性值是否唯一 136.public boolean isPropertyUnique(final String propertyName, final Object value) { 137.if (getHibernateTemplate().find(prepareWhereHql(propertyName + "=?"), value).size() > 0) 138.return false; 139.else 140.return true; 141. } 142. 143.// 刷新 144.public void flush() { 145. getHibernateTemplate().flush(); 146. } 147. 148.// 取得对象的主键名 149.public String getIdName() { 150. ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass); 151.return meta.getIdentifierPropertyName(); 152. } 153. 154./* 155. * 辅助方法 156.*/ 157.// select * from <T> 158.private String prepareSelectHql() { 159.return "from " + entityClass.getName(); 160. } 161. 162.// select * from <T> where 163.private String prepareWhereHql(String where) { 164.return prepareSelectHql() + " where " + where; 165. 166. } 167. 168.// select count(*) 169.private String prepareCountHql(String hql) { 170. String countHql = "select count (*) " + removeSelect(removeOrders(hql)); 171.return countHql; 172. } 173. 174.// 创建查询对象 175.private Query createQuery(Session session, final String hql, final Object... values) { 176. AssertUtils.hasText(hql, "hql不能为空"); 177.Query query = session.createQuery(hql); 178.if (values != null) { 179.for (int i = 0; i < values.length; i++) { 180. query.setParameter(i, values[i]); 181. } 182. } 183.return query; 184. } 185. 186.// hql中删除select 187.private String removeSelect(String hql) { 188.int beginPos = hql.toLowerCase().indexOf("from"); 189.return hql.substring(beginPos); 190. } 191. 192.// hql中删除order by 193.private String removeOrders(String hql) { 194. Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE); 195. Matcher m = p.matcher(hql); 196. StringBuffer sb = new StringBuffer(); 197.while (m.find()) { 198. m.appendReplacement(sb, ""); 199. } 200. m.appendTail(sb); 201.return sb.toString(); 202. } 203.} package jj.utils; import java.io.Serializable; import java.sql.SQLException; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.metadata.ClassMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; /** * 泛型HibernateDAO基类, 参照SpringSide4 * * @param<T> DAO操作的对象类型 * * @author jj * @version 0.1 */ public abstract class HibernateDao<T> extends HibernateDaoSupport { protected Logger log = LoggerFactory.getLogger(getClass()); protected Class<T> entityClass; // 通过子类的泛型定义设置实体对象类型 public HibernateDao() { this.entityClass = ReflectionUtils.getSuperClassGenricType(getClass()); } // 通过构造函数设置实体对象类型 public HibernateDao(Class<T> entityClass) { this.entityClass = entityClass; } // 自动注入SessionFactory @Autowired public void setupSessionFactory(final SessionFactory sessionFactory) { this.setSessionFactory(sessionFactory); } // 保存新增或修改的对象 public void save(final T entity) { AssertUtils.notNull(entity, "entity不能为空"); getHibernateTemplate().save(entity); log.debug("save entity: {}", entity); } // 删除对象 public void delete(final T entity) { AssertUtils.notNull(entity, "entity不能为空"); getHibernateTemplate().delete(entity); log.debug("delete entity: {}", entity); } // 按id删除对象 public void delete(Serializable id) { AssertUtils.notNull(id, "id不能为空"); delete(getById(id)); log.debug("delete entity {},id is {}", entityClass.getSimpleName(), id); } // 按id获取对象 public T getById(final Serializable id) { AssertUtils.notNull(id, "id不能为空"); return (T) getHibernateTemplate().get(entityClass, id); } // 获取全部对象列表 public List<T> getAll() { return getHibernateTemplate().find(prepareSelectHql()); } // 查询对象列表 public <X> List<X> query(final String hql, final Object... values) { return getHibernateTemplate().find(hql, values); } // 条件查询对象列表 public List<T> queryWhere(final String where, final Object... values) { return getHibernateTemplate().find(prepareWhereHql(where), values); } // 分页查询对象列表 public <X> PageResult<X> queryPage(final int offset, final int length, final String hql, final Object... values) { List list = getHibernateTemplate().executeFind(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = createQuery(session, hql, values); query.setFirstResult(offset); query.setMaxResults(length); List list = query.list(); return list; } }); PageResult res = new PageResult(); res.setOffset(offset); res.setLength(list.size()); res.setTotal(getCount(hql, values)); res.setResult(list); return res; } // 分页条件查询对象列表 public PageResult<T> queryPageWhere(final int offset, final int length, final String where, final Object... values) { return queryPage(offset, length, prepareWhereHql(where), values); } // 分页查询所有对象列表 public PageResult<T> queryPageAll(final int offset, final int length) { return queryPage(offset, length, prepareSelectHql()); } // 执行count查询获得本次Hql查询所能获得的对象总数 public long getCount(final String hql, final Object... values) { return getHibernateTemplate().execute(new HibernateCallback<Long>() { public Long doInHibernate(Session session) throws HibernateException, SQLException { return (Long) createQuery(session, prepareCountHql(hql), values).uniqueResult(); } }); } // 批量执行 public int batchExecute(final String hql, final Object... values) { return getHibernateTemplate().execute(new HibernateCallback<Integer>() { public Integer doInHibernate(Session session) throws HibernateException, SQLException { return (Integer) createQuery(session, hql, values).executeUpdate(); } }); } // 判断属性值是否唯一 public boolean isPropertyUnique(final String propertyName, final Object value) { if (getHibernateTemplate().find(prepareWhereHql(propertyName + "=?"), value).size() > 0) return false; else return true; } // 刷新 public void flush() { getHibernateTemplate().flush(); } // 取得对象的主键名 public String getIdName() { ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass); return meta.getIdentifierPropertyName(); } /* * 辅助方法 */ // select * from <T> private String prepareSelectHql() { return "from " + entityClass.getName(); } // select * from <T> where private String prepareWhereHql(String where) { return prepareSelectHql() + " where " + where; } // select count(*) private String prepareCountHql(String hql) { String countHql = "select count (*) " + removeSelect(removeOrders(hql)); return countHql; } // 创建查询对象 private Query createQuery(Session session, final String hql, final Object... values) { AssertUtils.hasText(hql, "hql不能为空"); Query query = session.createQuery(hql); if (values != null) { for (int i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } } return query; } // hql中删除select private String removeSelect(String hql) { int beginPos = hql.toLowerCase().indexOf("from"); return hql.substring(beginPos); } // hql中删除order by private 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(); } } 使用也很简单,直接指定实体类继承就行了,比如 [java] view plaincopyprint? 1.// ... 2.@Repository 3.public class UserDao extends HibernateDao<User> { 4.// ...特殊方法... 5.} // ... @Repository public class UserDao extends HibernateDao<User> { // ...特殊方法... } Spring通过注解自动注入,根本不用去动context.xml配置,有特殊方法也可以在继承的DAO里实现,程序的配置文件工作越来越少,层次越来越清晰!另外两个辅助的AssertUtils和ReflectionUtils直接从springside里拿来用了。 PageResult.java [java] view plaincopyprint? 1.package jj.utils; 2. 3.import java.util.Iterator; 4.import java.util.List; 5. 6./** 7. * HibernateDao分页查询的结果集封装 8. * 9. * @author jj 10. * 11. */ 12.public class PageResult<T> implements Iterable<T> { 13.private List<T> result = null; 14.private long total = -1; 15.private long offset = -1; 16.private long length = -1; 17. 18.// 实现Iterable接口, 可以for(Object item : page)遍历使用 19.@Override 20.public Iterator<T> iterator() { 21.return result.iterator(); 22. } 23. ... setter/getter ... package jj.utils; import java.util.Iterator; import java.util.List; /** * HibernateDao分页查询的结果集封装 * * @author jj * */ public class PageResult<T> implements Iterable<T> { private List<T> result = null; private long total = -1; private long offset = -1; private long length = -1; // 实现Iterable接口, 可以for(Object item : page)遍历使用 @Override public Iterator<T> iterator() { return result.iterator(); } ... setter/getter ... PS:springside确实是个好东东,作者很厉害,即使不拿来用在项目里,也是学习spring及相关技术的生动教材,赞一个!
反射工具类:
import java.lang.reflect.ParameterizedType; public class ReflectUtils { @SuppressWarnings("unchecked") public static <T> Class<T> getClassGenricType(final Class clazz) { return (Class<T>)((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0]; } }
这里的getClass()方法是获得继承HibernateDao的类(UserDao、RoleDao)
getGenericSuperclass()方法就是通过这些继承了HibernateDao的类,来得到父类(父类就是HibernateDao)的泛型。注意这个方法的返回值为Type,这是一个类型接口。请参考API。
因为在继承HibernateDao 的时候,会给它加一个泛型参数。比如,User、Role实体类。因此超类是参数化类型,所以返回的 Type 对象包含所使用的实际类型参数。这里返回的Type对象是ParameterizedType接口的实现类ParameterizedTypeImpl,所以要将返回类型转型为ParameterizedType。
getActualTypeArguments()方法是ParameterizedType接口中的,它的作用就是获得实际类型参数 Type 对象的数组,因为我们这里只定义了一个泛型参数,数组里面也只有一个值,所以需要在数组下标处填0。然后最后一步转型千万别忘记了,因为这个方法返回的可是一个Type数组喔。
如果对于这部分的说明还有点不理解的话,请到时候有了代码,设个断点跟踪一下,就会全部清楚了。关于java反射,它已经超出本文的范围。大象只对本例中用到的部分进行讲解。