泛型HibernateDAO的实现

可能是考虑适用性和作者的习惯,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及相关技术的生动教材,赞一个!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值