泛型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及相关技术的生动教材,赞一个!

 

反射工具类:

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反射,它已经超出本文的范围。大象只对本例中用到的部分进行讲解。

你可能感兴趣的:(泛型HibernateDAO的实现)