泛型HibernateDAO的實現

 

多是考慮適用性和做者的習慣,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的類(UserDaoRoleDao
getGenericSuperclass()方法就是經過這些繼承了HibernateDao的類,來獲得父類(父類就是HibernateDao)的泛型。注意這個方法的返回值爲Type,這是一個類型接口。請參考API
由於在繼承HibernateDao 的時候,會給它加一個泛型參數。好比,UserRole實體類。所以超類是參數化類型,因此返回的 Type 對象包含所使用的實際類型參數。這裏返回的Type對象是ParameterizedType接口的實現類ParameterizedTypeImpl因此要將返回類型轉型爲ParameterizedType
getActualTypeArguments()方法是ParameterizedType接口中的,它的做用就是得到實際類型參數 Type 對象的數組,由於咱們這裏只定義了一個泛型參數,數組裏面也只有一個值,因此須要在數組下標處填0。而後最後一步轉型千萬別忘記了,由於這個方法返回的但是一個Type數組喔。
若是對於這部分的說明還有點不理解的話,請到時候有了代碼,設個斷點跟蹤一下,就會所有清楚了。關於java反射,它已經超出本文的範圍。大象只對本例中用到的部分進行講解。
spring

相關文章
相關標籤/搜索