可能是考虑适用性和作者的习惯,SpringSide没有基于Spring提供的HibernateDaoSupport,没有用HibernateTemplate实现,而是直接操作Hibernate,大量使用Criteria构建查询,这和我的习惯有很大不同。本着简单实用快速的原则,参照spring边上的思路,自己实现了下面这个泛型DAO,实现了基本的CRUD,hql查询,分页等功能,基本满足日常需要。
HibernateDao.java
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();
}
}
使用也很简单,直接指定实体类继承就行了,比如
// ...
@Repository
public class UserDao extends HibernateDao<User> {
// ...特殊方法...
}
Spring通过注解自动注入,根本不用去动context.xml配置,有特殊方法也可以在继承的DAO里实现,程序的配置文件工作越来越少,层次越来越清晰!另外两个辅助的AssertUtils和ReflectionUtils直接从springside里拿来用了。
PageResult.java
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及相关技术的生动教材,赞一个!