多是考慮適用性和做者的習慣,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及相關技術的生動教材,贊一個!
反射工具類:java
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反射,它已經超出本文的範圍。大象只對本例中用到的部分進行講解。
spring