改进版的hibernate泛型dao(依赖spring)
2008-12-26 10:23
309 查看
结构看图:
HinernateEntityDao和HibernateGenericDao都继承在spring的HibernateDaoSupport
一个提供和实体相关的操作,一个提供和实体类无关的操作。
然后以组合的方式在BaseDao中使用,这样程序中全部使用IBaseDao接口来操作数据,便于修改和维护.
xml配置实用如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-这个是和实体相关的dao,所以scope是prototype的每个实体对应一个对象->
<bean id="hedao"
class="com.hibernate.dao.extend.HibernateEntityDao" scope="prototype" lazy-init="true">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-这个和具体实体无关,所有dao共享->
<bean id="hgdao"
class="com.hibernate.dao.generic.HibernateGenericDao">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--使用泛型DAO作为抽象基类-->
<bean id="baseDao" class="com.hibernate.dao.base.BaseDao"
abstract="true" depends-on="hedao,hgdao">
<property name="hedao">
<ref bean="hedao" />
</property>
<property name="hgdao">
<ref bean="hgdao" />
</property>
</bean>
<!-- 配置实体Demodata的DAO -->
<bean id="demoDao" parent="baseDao">
<constructor-arg>
<value>com.hibernate.entityclass.Demodata</value>
</constructor-arg>
</bean>
</beans>
代码:
BaseDao.java
package com.hibernate.dao.base;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.hibernate.dao.extend.HibernateEntityDao;
import com.hibernate.dao.generic.HibernateGenericDao;
import com.hibernate.dao.support.Page;
/**
* 提供hibernate dao的所有操作,<br>
* 实现类由spring注入HibernateEntityDao和HibernateGenericDao来实现
*
*/
public class BaseDao<T,PK extends Serializable> implements IBaseDao<T,PK> {
protected Class<T> entityClass;// DAO所管理的Entity类型.
private HibernateEntityDao<T,PK> hedao;
private HibernateGenericDao hgdao;
public void setHedao(HibernateEntityDao<T, PK> hedao) {
hedao.setEntityClass(entityClass);
this.hedao = hedao;
}
public void setHgdao(HibernateGenericDao hgdao) {
this.hgdao = hgdao;
}
/**
*让spring提供构造函数注入
*/
public BaseDao(Class<T> type) {
this.entityClass = type;
}
public BaseDao(){}
/**
* 清除所有对象缓存
*/
public void clear() {
hgdao.clear();
}
/**
* 创建Criteria对象.
* @param criterions 可变的Restrictions条件列表
*/
public Criteria createCriteria(Criterion... criterions) {
return hedao.createCriteria(criterions);
}
/**
* 创建Criteria对象,带排序字段与升降序字段.
*/
public Criteria createCriteria(String orderBy, boolean isAsc,
Criterion... criterions) {
return hedao.createCriteria(orderBy, isAsc, criterions);
}
/**
* 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* 留意可以连续设置,如下:
* <pre>
* dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
* </pre>
* 调用方式如下:
* <pre>
* dao.createQuery(hql)
* dao.createQuery(hql,arg0);
* dao.createQuery(hql,arg0,arg1);
* dao.createQuery(hql,new Object[arg0,arg1,arg2])
* </pre>
*
* @param values 可变参数.
*/
public Query createQuery(String hql, Object... values) {
return hgdao.createQuery(hql, values);
}
/**
* @param hql 查询sql
* @param start 分页从哪一条数据开始
* @param pageSize 每一个页面的大小
* @param values 查询条件
* @return page对象
*/
public Page dataQuery(String hql, int start, int pageSize, Object... values) {
return hgdao.dataQuery(hql, start, pageSize, values);
}
/**
* 消除与 Hibernate Session 的关联
* @param entity
*/
public void evit(T entity) {
hedao.evict(entity);
}
/**
* 执行本地sql语句获得标量数值列表
*/
@SuppressWarnings("unchecked")
public List executeNativeSql(String sql) {
return hgdao.executeNativeSql(sql);
}
/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
* @param values 可变参数
*/
@SuppressWarnings("unchecked")
public List find(String hql, Object... values) {
return hgdao.find(hql, values);
}
/**
* 根据属性名和属性值查询对象.
* @return 符合条件的对象列表
*/
public List<T> findBy(String propertyName, Object value) {
return hedao.findBy(propertyName, value);
}
/**
* 根据属性名和属性值查询对象,带排序参数.
*/
public List<T> findBy(String propertyName, Object value, String orderBy,
boolean isAsc) {
return hedao.findBy(propertyName, value, orderBy, isAsc);
}
/**
* 根据属性名和属性值查询唯一对象.
* @return 符合条件的唯一对象 or null if not found.
*/
public T findUniqueBy(String propertyName, Object value) {
return hedao.findUniqueBy(propertyName, value);
}
/**
* 执行一些必须的sql语句把内存中的对象同步到jdbc的链接中
*/
public void flush() {
hgdao.flush();
}
/**
* 根据Serializable类型的id获取实体对象<p/>
* 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
* @param id
*/
public T get(PK id) {
return hedao.get(id);
}
/**
* 获取实体类型的全部对象
*/
public List<T> getAll() {
return hedao.getAll();
}
/**
* 获取全部对象,带排序字段与升降序参数.
*/
public List<T> getAll(String orderBy, boolean isAsc) {
return hedao.getAll(orderBy, isAsc);
}
/**
* 直接使用spring提供的HibernateTemplate
*/
public HibernateTemplate getHibernateTemplate() {
return hgdao.getHibernateTemplate();
}
/**
* 判断对象某些属性的值在数据库中是否唯一.
*
* @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
*/
public boolean isUnique(T entity, String uniquePropertyNames) {
return hedao.isUnique(entity, uniquePropertyNames);
}
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
public Page pagedQuery(String hql, int pageNo, int pageSize,
Object... values) {
return hgdao.pagedQuery(hql, pageNo, pageSize, values);
}
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
return hedao.pagedQuery(criteria, pageNo, pageSize);
}
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, Criterion... criterions) {
return hedao.pagedQuery(pageNo, pageSize, criterions);
}
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, String orderBy,
boolean isAsc, Criterion... criterions) {
return hedao.pagedQuery(pageNo, pageSize, orderBy, isAsc, criterions);
}
/**
* 删除对象.
*/
public void remove(T entity) {
hedao.remove(entity);
}
/**
* 根据ID删除对象.
*/
public void removeById(PK id) {
hedao.removeById(id);
}
/**
* 保存对象.<br>
* 如果对象已在本session中持久化了,不做任何事。<br>
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
* 如果没有持久化标识属性,调用save()。<br>
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
* 如果是附带版本信息的(<version>或<timestamp>)且版本属性表明为新的实例化对象就save()。<br>
* 否则调用update()重新关联托管对象
*/
public void save(T entity) {
hedao.save(entity);
}
/**
* 在不同的session中关联修改过的托管对象
*/
public void update(T entity){
hedao.update(entity);
}
}
IBase.java
/**
*
*/
package com.hibernate.dao.base;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.hibernate.dao.generic.HibernateGenericDao;
import com.hibernate.dao.support.Page;
/**
* 提供hibernate dao的所有操作,<br>
* 实现类由spring注入HibernateEntityDao和HibernateGenericDao来实现
*
*/
public interface IBaseDao<T,PK extends Serializable> {
/**
* 获取全部对象
*
* @see HibernateGenericDao#getAll(Class)
*/
public List<T> getAll();
/**
* 获取全部对象,带排序参数.
*/
public List<T> getAll(String orderBy, boolean isAsc);
/**
* 根据ID移除对象.
*/
public void removeById(PK id);
/**
* 取得Entity的Criteria.
*/
public Criteria createCriteria(Criterion... criterions);
/**
* 取得Entity的Criteria,带排序参数.
*/
public Criteria createCriteria(String orderBy, boolean isAsc,
Criterion... criterions);
/**
* 根据属性名和属性值查询对象.
*
* @return 符合条件的对象列表
*/
public List<T> findBy(String propertyName, Object value);
/**
* 根据属性名和属性值查询对象,带排序参数.
*
* @return 符合条件的对象列表
*/
public List<T> findBy(String propertyName, Object value, String orderBy,
boolean isAsc);
/**
* 根据属性名和属性值查询单个对象.
*
* @return 符合条件的唯一对象 or null
*/
public T findUniqueBy(String propertyName, Object value);
/**
* 判断对象某些属性的值在数据库中唯一.
*
* @param uniquePropertyNames
* 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
* @see HibernateGenericDao#isUnique(Class,Object,String)
*/
public boolean isUnique(T entity, String uniquePropertyNames);
/**
* 消除与 Hibernate Session 的关联
*
*/
public void evit(T entity);
/**
* 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
*/
public T get(PK id);
/**
* 保存对象.
*/
public void save(T o);
/**
* 删除对象.
*/
public void remove(T o);
public void flush();
public void clear();
/**
* 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* 留意可以连续设置,如下:
* <pre>
* dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
* </pre>
* 调用方式如下:
* <pre>
* dao.createQuery(hql)
* dao.createQuery(hql,arg0);
* dao.createQuery(hql,arg0,arg1);
* dao.createQuery(hql,new Object[arg0,arg1,arg2])
* </pre>
*
* @param values 可变参数.
*/
public Query createQuery(String hql, Object... values);
/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
*/
@SuppressWarnings("unchecked")
public List find(String hql, Object... values);
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values);
/**
* @param hql 查询sql
* @param start 分页从哪一条数据开始
* @param pageSize 每一个页面的大小
* @param values 查询条件
* @return page对象
*/
public Page dataQuery(String hql, int start, int pageSize, Object... values);
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize);
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, Criterion... criterions);
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, String orderBy, boolean isAsc,
Criterion... criterions);
@SuppressWarnings("unchecked")
public List executeNativeSql(String sql);
public HibernateTemplate getHibernateTemplate();
/**
* 在不同的session中关联修改过的托管对象
*/
public void update(T entity);
}
HibernateEntityDao.java
/**
*
*/
package com.hibernate.dao.extend;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import com.hibernate.dao.support.BeanUtils;
import com.hibernate.dao.support.Page;
/**
* 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类. <p/>
* 子类只要在类定义时指定所管理Entity的Class,
* 即拥有对单个Entity对象的CRUD操作.
*
* @see 继承自spring的HibernateDaoSupport
*/
public class HibernateEntityDao<T,PK extends Serializable> extends HibernateDaoSupport implements IEntityDao<T, PK> {
protected Class<T> entityClass;// DAO所管理的Entity类型.
public void setEntityClass(Class<T> type){
this.entityClass=type;
}
/**
* 在构造函数中将泛型T.class赋给entityClass.
*/
public HibernateEntityDao() {
//entityClass = GenericsUtils.getSuperClassGenricType(getClass());
}
/**
* 取得entityClass.JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
*/
protected Class<T> getEntityClass() {
return entityClass;
}
/**
* 根据Serializable类型的id获取实体对象<p/>
* 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
* @param id
*/
@SuppressWarnings("unchecked")
public T get(PK id) {
return (T) getHibernateTemplate().load(getEntityClass(), id);
}
/**
* 获取实体类型的全部对象
*/
@SuppressWarnings("unchecked")
public List<T> getAll() {
return (List<T>)(getHibernateTemplate().loadAll(getEntityClass()));
}
/**
* 获取全部对象,带排序字段与升降序参数.
*/
@SuppressWarnings("unchecked")
public List<T> getAll(String orderBy, boolean isAsc) {
Assert.hasText(orderBy);
if (isAsc)
return getHibernateTemplate().findByCriteria(
DetachedCriteria.forClass(getEntityClass()).addOrder(Order.asc(orderBy)));
else
return getHibernateTemplate().findByCriteria(
DetachedCriteria.forClass(getEntityClass()).addOrder(Order.desc(orderBy)));
}
/**
* 删除对象.
*/
public void remove(T entity) {
getHibernateTemplate().delete(entity);
}
/**
* 根据ID删除对象.
*/
public void removeById(PK id) {
remove(get(id));
}
/**
* 保存对象.<br>
* 如果对象已在本session中持久化了,不做任何事。<br>
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
* 如果没有持久化标识属性,调用save()。<br>
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
* 如果是附带版本信息的(<version>或<timestamp>)且版本属性表明为新的实例化对象就save()。<br>
* 否则调用update()重新关联托管对象
*/
public void save(T entity) {
getHibernateTemplate().saveOrUpdate(entity);
}
/**
* 在不同的session中关联修改过的托管对象
*/
public void update(T entity) {
getHibernateTemplate().update(entity);
}
/**
* 消除与 Hibernate Session 的关联
* @param entity
*/
public void evict(T entity) {
getHibernateTemplate().evict(entity);
}
/**
* 创建Criteria对象.
* @param criterions 可变的Restrictions条件列表
*/
public Criteria createCriteria(Criterion... criterions) {
Criteria criteria = getSession().createCriteria(getEntityClass());
for (Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}
/**
* 创建Criteria对象,带排序字段与升降序字段.
*/
public Criteria createCriteria(String orderBy, boolean isAsc, Criterion... criterions) {
Assert.hasText(orderBy);
Criteria criteria = createCriteria(criterions);
if (isAsc)
criteria.addOrder(Order.asc(orderBy));
else
criteria.addOrder(Order.desc(orderBy));
return criteria;
}
/**
* 根据属性名和属性值查询对象.
* @return 符合条件的对象列表
*/
@SuppressWarnings("unchecked")
public List<T> findBy(String propertyName, Object value) {
Assert.hasText(propertyName);
return createCriteria(Restrictions.eq(propertyName, value)).list();
}
/**
* 根据属性名和属性值查询对象,带排序参数.
*/
@SuppressWarnings("unchecked")
public List<T> findBy(String propertyName, Object value, String orderBy, boolean isAsc) {
Assert.hasText(propertyName);
Assert.hasText(orderBy);
return createCriteria(orderBy, isAsc, Restrictions.eq(propertyName, value)).list();
}
/**
* 根据属性名和属性值查询唯一对象.
* @return 符合条件的唯一对象 or null if not found.
*/
@SuppressWarnings("unchecked")
public T findUniqueBy(String propertyName, Object value) {
Assert.hasText(propertyName);
return (T) createCriteria(Restrictions.eq(propertyName, value)).uniqueResult();
}
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
@SuppressWarnings("unchecked")
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
Assert.notNull(criteria);
Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
CriteriaImpl impl = (CriteriaImpl) criteria;
// 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
Projection projection = impl.getProjection();
List<CriteriaImpl.OrderEntry> orderEntries;
try {
orderEntries = (List) BeanUtils.forceGetProperty(impl, "orderEntries");
BeanUtils.forceSetProperty(impl, "orderEntries", new ArrayList());
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
}
// 执行查询
int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
// 将之前的Projection和OrderBy条件重新设回去
criteria.setProjection(projection);
if (projection == null) {
criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
try {
BeanUtils.forceSetProperty(impl, "orderEntries", orderEntries);
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
}
// 返回分页对象
if (totalCount < 1)
return new Page();
int startIndex = Page.getStartOfPage(pageNo, pageSize);;
List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, Criterion... criterions) {
Criteria criteria = createCriteria(criterions);
return pagedQuery(criteria, pageNo, pageSize);
}
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, String orderBy, boolean isAsc,
Criterion... criterions) {
Criteria criteria = createCriteria(orderBy, isAsc, criterions);
return pagedQuery(criteria, pageNo, pageSize);
}
/**
* 判断对象某些属性的值在数据库中是否唯一.
*
* @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
*/
public boolean isUnique(T entity, String uniquePropertyNames) {
Assert.hasText(uniquePropertyNames);
Criteria criteria = createCriteria().setProjection(Projections.rowCount());
String[] nameList = uniquePropertyNames.split(",");
try {
// 循环加入唯一列
for (String name : nameList) {
criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));
}
// 以下代码为了如果是update的情况,排除entity自身.
String idName = getIdName(getEntityClass());
// 取得entity的主键值
PK id = getId(getEntityClass(), entity);
// 如果id!=null,说明对象已存在,该操作为update,加入排除自身的判断
if (id != null)
criteria.add(Restrictions.not(Restrictions.eq(idName, id)));
} catch (Exception e) {
ReflectionUtils.handleReflectionException(e);
}
return (Integer) criteria.uniqueResult() == 0;
}
/**
* 取得对象的主键值,辅助函数.
*/
@SuppressWarnings("unchecked")
public PK getId(Class<T> entityClass, T entity) throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
Assert.notNull(entity);
Assert.notNull(entityClass);
return (PK) PropertyUtils.getProperty(entity, getIdName(entityClass));
}
/**
* 取得对象的主键名,辅助函数.
*/
public String getIdName(Class<T> clazz) {
Assert.notNull(clazz);
ClassMetadata meta = getSessionFactory().getClassMetadata(clazz);
Assert.notNull(meta, "Class " + clazz + " not define in hibernate session factory.");
String idName = meta.getIdentifierPropertyName();
Assert.hasText(idName, clazz.getSimpleName() + " has no identifier property define.");
return idName;
}
}
IEntityDao.java
package com.hibernate.dao.extend;
import java.io.Serializable;
import java.util.List;
/**
* 针对单个Entity对象的CRUD操作定义.
*/
public interface IEntityDao<T,PK extends Serializable> {
T get(PK id);
List<T> getAll();
void save(T entity);
void remove(T entity);
void removeById(PK id);
void update(T entity);
/**
* 获取Entity对象的主键名.
*/
String getIdName(Class<T> clazz);
}
HibernateGenericDao.java
/**
*
*/
package com.hibernate.dao.generic;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.Query;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import com.hibernate.dao.support.Page;
/**
* 继承自spring的HibernateDaoSupport<br>
* 提供了和具体实体类无关的数据库操作,如分页函数和若干便捷查询方法
* @see HibernateDaoSupport
*/
public class HibernateGenericDao extends HibernateDaoSupport {
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
@SuppressWarnings("unchecked")
public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
Assert.hasText(hql);
Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
// Count查询
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
List countlist = getHibernateTemplate().find(countQueryString, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page();
// 实际查询返回分页对象
int startIndex = Page.getStartOfPage(pageNo, pageSize);
Query query = createQuery(hql, values);
List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* @param hql 查询sql
* @param start 分页从哪一条数据开始
* @param pageSize 每一个页面的大小
* @param values 查询条件
* @return page对象
*/
@SuppressWarnings("unchecked")
public Page dataQuery(String hql, int start, int pageSize, Object... values){
Assert.hasText(hql);
// Count查询
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
List countlist = getHibernateTemplate().find(countQueryString, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page();
// 实际查询返回分页对象
int startIndex = start;
Query query = createQuery(hql, values);
List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* 留意可以连续设置,如下:
* <pre>
* dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
* </pre>
* 调用方式如下:
* <pre>
* dao.createQuery(hql)
* dao.createQuery(hql,arg0);
* dao.createQuery(hql,arg0,arg1);
* dao.createQuery(hql,new Object[arg0,arg1,arg2])
* </pre>
*
* @param values 可变参数.
*/
public Query createQuery(String hql, Object... values) {
Assert.hasText(hql);
Query query = getSession().createQuery(hql);
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
return query;
}
/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
* @param values 可变参数
*/
@SuppressWarnings("unchecked")
public List find(String hql, Object... values) {
Assert.hasText(hql);
return getHibernateTemplate().find(hql, values);
}
/**
* 执行一些必须的sql语句把内存中的对象同步到jdbc的链接中
*/
public void flush() {
getHibernateTemplate().flush();
}
/**
* 清除所有对象缓存
*/
public void clear() {
getHibernateTemplate().clear();
}
/**
* 执行本地sql语句获得标量数值列表
*/
@SuppressWarnings("unchecked")
public List executeNativeSql(String sql){
return getSession().createSQLQuery(sql).list();
}
/**
* 去除hql的select 子句,未考虑union的情况,用于pagedQuery.
*/
private static String removeSelect(String hql) {
Assert.hasText(hql);
int beginPos = hql.toLowerCase().indexOf("from");
Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
return hql.substring(beginPos);
}
/**
* 去除hql的orderby 子句,用于pagedQuery.
*/
private static String removeOrders(String hql) {
Assert.hasText(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();
}
}
com.hibernate.dao.support下的3个类和如下的一致:
http://blog.csdn.net/tom_221x/archive/2008/12/05/3453312.aspx
HinernateEntityDao和HibernateGenericDao都继承在spring的HibernateDaoSupport
一个提供和实体相关的操作,一个提供和实体类无关的操作。
然后以组合的方式在BaseDao中使用,这样程序中全部使用IBaseDao接口来操作数据,便于修改和维护.
xml配置实用如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-这个是和实体相关的dao,所以scope是prototype的每个实体对应一个对象->
<bean id="hedao"
class="com.hibernate.dao.extend.HibernateEntityDao" scope="prototype" lazy-init="true">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-这个和具体实体无关,所有dao共享->
<bean id="hgdao"
class="com.hibernate.dao.generic.HibernateGenericDao">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--使用泛型DAO作为抽象基类-->
<bean id="baseDao" class="com.hibernate.dao.base.BaseDao"
abstract="true" depends-on="hedao,hgdao">
<property name="hedao">
<ref bean="hedao" />
</property>
<property name="hgdao">
<ref bean="hgdao" />
</property>
</bean>
<!-- 配置实体Demodata的DAO -->
<bean id="demoDao" parent="baseDao">
<constructor-arg>
<value>com.hibernate.entityclass.Demodata</value>
</constructor-arg>
</bean>
</beans>
代码:
BaseDao.java
package com.hibernate.dao.base;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.hibernate.dao.extend.HibernateEntityDao;
import com.hibernate.dao.generic.HibernateGenericDao;
import com.hibernate.dao.support.Page;
/**
* 提供hibernate dao的所有操作,<br>
* 实现类由spring注入HibernateEntityDao和HibernateGenericDao来实现
*
*/
public class BaseDao<T,PK extends Serializable> implements IBaseDao<T,PK> {
protected Class<T> entityClass;// DAO所管理的Entity类型.
private HibernateEntityDao<T,PK> hedao;
private HibernateGenericDao hgdao;
public void setHedao(HibernateEntityDao<T, PK> hedao) {
hedao.setEntityClass(entityClass);
this.hedao = hedao;
}
public void setHgdao(HibernateGenericDao hgdao) {
this.hgdao = hgdao;
}
/**
*让spring提供构造函数注入
*/
public BaseDao(Class<T> type) {
this.entityClass = type;
}
public BaseDao(){}
/**
* 清除所有对象缓存
*/
public void clear() {
hgdao.clear();
}
/**
* 创建Criteria对象.
* @param criterions 可变的Restrictions条件列表
*/
public Criteria createCriteria(Criterion... criterions) {
return hedao.createCriteria(criterions);
}
/**
* 创建Criteria对象,带排序字段与升降序字段.
*/
public Criteria createCriteria(String orderBy, boolean isAsc,
Criterion... criterions) {
return hedao.createCriteria(orderBy, isAsc, criterions);
}
/**
* 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* 留意可以连续设置,如下:
* <pre>
* dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
* </pre>
* 调用方式如下:
* <pre>
* dao.createQuery(hql)
* dao.createQuery(hql,arg0);
* dao.createQuery(hql,arg0,arg1);
* dao.createQuery(hql,new Object[arg0,arg1,arg2])
* </pre>
*
* @param values 可变参数.
*/
public Query createQuery(String hql, Object... values) {
return hgdao.createQuery(hql, values);
}
/**
* @param hql 查询sql
* @param start 分页从哪一条数据开始
* @param pageSize 每一个页面的大小
* @param values 查询条件
* @return page对象
*/
public Page dataQuery(String hql, int start, int pageSize, Object... values) {
return hgdao.dataQuery(hql, start, pageSize, values);
}
/**
* 消除与 Hibernate Session 的关联
* @param entity
*/
public void evit(T entity) {
hedao.evict(entity);
}
/**
* 执行本地sql语句获得标量数值列表
*/
@SuppressWarnings("unchecked")
public List executeNativeSql(String sql) {
return hgdao.executeNativeSql(sql);
}
/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
* @param values 可变参数
*/
@SuppressWarnings("unchecked")
public List find(String hql, Object... values) {
return hgdao.find(hql, values);
}
/**
* 根据属性名和属性值查询对象.
* @return 符合条件的对象列表
*/
public List<T> findBy(String propertyName, Object value) {
return hedao.findBy(propertyName, value);
}
/**
* 根据属性名和属性值查询对象,带排序参数.
*/
public List<T> findBy(String propertyName, Object value, String orderBy,
boolean isAsc) {
return hedao.findBy(propertyName, value, orderBy, isAsc);
}
/**
* 根据属性名和属性值查询唯一对象.
* @return 符合条件的唯一对象 or null if not found.
*/
public T findUniqueBy(String propertyName, Object value) {
return hedao.findUniqueBy(propertyName, value);
}
/**
* 执行一些必须的sql语句把内存中的对象同步到jdbc的链接中
*/
public void flush() {
hgdao.flush();
}
/**
* 根据Serializable类型的id获取实体对象<p/>
* 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
* @param id
*/
public T get(PK id) {
return hedao.get(id);
}
/**
* 获取实体类型的全部对象
*/
public List<T> getAll() {
return hedao.getAll();
}
/**
* 获取全部对象,带排序字段与升降序参数.
*/
public List<T> getAll(String orderBy, boolean isAsc) {
return hedao.getAll(orderBy, isAsc);
}
/**
* 直接使用spring提供的HibernateTemplate
*/
public HibernateTemplate getHibernateTemplate() {
return hgdao.getHibernateTemplate();
}
/**
* 判断对象某些属性的值在数据库中是否唯一.
*
* @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
*/
public boolean isUnique(T entity, String uniquePropertyNames) {
return hedao.isUnique(entity, uniquePropertyNames);
}
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
public Page pagedQuery(String hql, int pageNo, int pageSize,
Object... values) {
return hgdao.pagedQuery(hql, pageNo, pageSize, values);
}
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
return hedao.pagedQuery(criteria, pageNo, pageSize);
}
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, Criterion... criterions) {
return hedao.pagedQuery(pageNo, pageSize, criterions);
}
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, String orderBy,
boolean isAsc, Criterion... criterions) {
return hedao.pagedQuery(pageNo, pageSize, orderBy, isAsc, criterions);
}
/**
* 删除对象.
*/
public void remove(T entity) {
hedao.remove(entity);
}
/**
* 根据ID删除对象.
*/
public void removeById(PK id) {
hedao.removeById(id);
}
/**
* 保存对象.<br>
* 如果对象已在本session中持久化了,不做任何事。<br>
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
* 如果没有持久化标识属性,调用save()。<br>
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
* 如果是附带版本信息的(<version>或<timestamp>)且版本属性表明为新的实例化对象就save()。<br>
* 否则调用update()重新关联托管对象
*/
public void save(T entity) {
hedao.save(entity);
}
/**
* 在不同的session中关联修改过的托管对象
*/
public void update(T entity){
hedao.update(entity);
}
}
IBase.java
/**
*
*/
package com.hibernate.dao.base;
import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Criterion;
import org.springframework.orm.hibernate3.HibernateTemplate;
import com.hibernate.dao.generic.HibernateGenericDao;
import com.hibernate.dao.support.Page;
/**
* 提供hibernate dao的所有操作,<br>
* 实现类由spring注入HibernateEntityDao和HibernateGenericDao来实现
*
*/
public interface IBaseDao<T,PK extends Serializable> {
/**
* 获取全部对象
*
* @see HibernateGenericDao#getAll(Class)
*/
public List<T> getAll();
/**
* 获取全部对象,带排序参数.
*/
public List<T> getAll(String orderBy, boolean isAsc);
/**
* 根据ID移除对象.
*/
public void removeById(PK id);
/**
* 取得Entity的Criteria.
*/
public Criteria createCriteria(Criterion... criterions);
/**
* 取得Entity的Criteria,带排序参数.
*/
public Criteria createCriteria(String orderBy, boolean isAsc,
Criterion... criterions);
/**
* 根据属性名和属性值查询对象.
*
* @return 符合条件的对象列表
*/
public List<T> findBy(String propertyName, Object value);
/**
* 根据属性名和属性值查询对象,带排序参数.
*
* @return 符合条件的对象列表
*/
public List<T> findBy(String propertyName, Object value, String orderBy,
boolean isAsc);
/**
* 根据属性名和属性值查询单个对象.
*
* @return 符合条件的唯一对象 or null
*/
public T findUniqueBy(String propertyName, Object value);
/**
* 判断对象某些属性的值在数据库中唯一.
*
* @param uniquePropertyNames
* 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
* @see HibernateGenericDao#isUnique(Class,Object,String)
*/
public boolean isUnique(T entity, String uniquePropertyNames);
/**
* 消除与 Hibernate Session 的关联
*
*/
public void evit(T entity);
/**
* 根据ID获取对象. 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
*/
public T get(PK id);
/**
* 保存对象.
*/
public void save(T o);
/**
* 删除对象.
*/
public void remove(T o);
public void flush();
public void clear();
/**
* 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* 留意可以连续设置,如下:
* <pre>
* dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
* </pre>
* 调用方式如下:
* <pre>
* dao.createQuery(hql)
* dao.createQuery(hql,arg0);
* dao.createQuery(hql,arg0,arg1);
* dao.createQuery(hql,new Object[arg0,arg1,arg2])
* </pre>
*
* @param values 可变参数.
*/
public Query createQuery(String hql, Object... values);
/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
*/
@SuppressWarnings("unchecked")
public List find(String hql, Object... values);
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values);
/**
* @param hql 查询sql
* @param start 分页从哪一条数据开始
* @param pageSize 每一个页面的大小
* @param values 查询条件
* @return page对象
*/
public Page dataQuery(String hql, int start, int pageSize, Object... values);
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize);
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, Criterion... criterions);
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, String orderBy, boolean isAsc,
Criterion... criterions);
@SuppressWarnings("unchecked")
public List executeNativeSql(String sql);
public HibernateTemplate getHibernateTemplate();
/**
* 在不同的session中关联修改过的托管对象
*/
public void update(T entity);
}
HibernateEntityDao.java
/**
*
*/
package com.hibernate.dao.extend;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.metadata.ClassMetadata;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import com.hibernate.dao.support.BeanUtils;
import com.hibernate.dao.support.Page;
/**
* 负责为单个Entity对象提供CRUD操作的Hibernate DAO基类. <p/>
* 子类只要在类定义时指定所管理Entity的Class,
* 即拥有对单个Entity对象的CRUD操作.
*
* @see 继承自spring的HibernateDaoSupport
*/
public class HibernateEntityDao<T,PK extends Serializable> extends HibernateDaoSupport implements IEntityDao<T, PK> {
protected Class<T> entityClass;// DAO所管理的Entity类型.
public void setEntityClass(Class<T> type){
this.entityClass=type;
}
/**
* 在构造函数中将泛型T.class赋给entityClass.
*/
public HibernateEntityDao() {
//entityClass = GenericsUtils.getSuperClassGenricType(getClass());
}
/**
* 取得entityClass.JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
*/
protected Class<T> getEntityClass() {
return entityClass;
}
/**
* 根据Serializable类型的id获取实体对象<p/>
* 实际调用Hibernate的session.load()方法返回实体或其proxy对象. 如果对象不存在,抛出异常.
* @param id
*/
@SuppressWarnings("unchecked")
public T get(PK id) {
return (T) getHibernateTemplate().load(getEntityClass(), id);
}
/**
* 获取实体类型的全部对象
*/
@SuppressWarnings("unchecked")
public List<T> getAll() {
return (List<T>)(getHibernateTemplate().loadAll(getEntityClass()));
}
/**
* 获取全部对象,带排序字段与升降序参数.
*/
@SuppressWarnings("unchecked")
public List<T> getAll(String orderBy, boolean isAsc) {
Assert.hasText(orderBy);
if (isAsc)
return getHibernateTemplate().findByCriteria(
DetachedCriteria.forClass(getEntityClass()).addOrder(Order.asc(orderBy)));
else
return getHibernateTemplate().findByCriteria(
DetachedCriteria.forClass(getEntityClass()).addOrder(Order.desc(orderBy)));
}
/**
* 删除对象.
*/
public void remove(T entity) {
getHibernateTemplate().delete(entity);
}
/**
* 根据ID删除对象.
*/
public void removeById(PK id) {
remove(get(id));
}
/**
* 保存对象.<br>
* 如果对象已在本session中持久化了,不做任何事。<br>
* 如果另一个seesion拥有相同的持久化标识,抛出异常。<br>
* 如果没有持久化标识属性,调用save()。<br>
* 如果持久化标识表明是一个新的实例化对象,调用save()。<br>
* 如果是附带版本信息的(<version>或<timestamp>)且版本属性表明为新的实例化对象就save()。<br>
* 否则调用update()重新关联托管对象
*/
public void save(T entity) {
getHibernateTemplate().saveOrUpdate(entity);
}
/**
* 在不同的session中关联修改过的托管对象
*/
public void update(T entity) {
getHibernateTemplate().update(entity);
}
/**
* 消除与 Hibernate Session 的关联
* @param entity
*/
public void evict(T entity) {
getHibernateTemplate().evict(entity);
}
/**
* 创建Criteria对象.
* @param criterions 可变的Restrictions条件列表
*/
public Criteria createCriteria(Criterion... criterions) {
Criteria criteria = getSession().createCriteria(getEntityClass());
for (Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}
/**
* 创建Criteria对象,带排序字段与升降序字段.
*/
public Criteria createCriteria(String orderBy, boolean isAsc, Criterion... criterions) {
Assert.hasText(orderBy);
Criteria criteria = createCriteria(criterions);
if (isAsc)
criteria.addOrder(Order.asc(orderBy));
else
criteria.addOrder(Order.desc(orderBy));
return criteria;
}
/**
* 根据属性名和属性值查询对象.
* @return 符合条件的对象列表
*/
@SuppressWarnings("unchecked")
public List<T> findBy(String propertyName, Object value) {
Assert.hasText(propertyName);
return createCriteria(Restrictions.eq(propertyName, value)).list();
}
/**
* 根据属性名和属性值查询对象,带排序参数.
*/
@SuppressWarnings("unchecked")
public List<T> findBy(String propertyName, Object value, String orderBy, boolean isAsc) {
Assert.hasText(propertyName);
Assert.hasText(orderBy);
return createCriteria(orderBy, isAsc, Restrictions.eq(propertyName, value)).list();
}
/**
* 根据属性名和属性值查询唯一对象.
* @return 符合条件的唯一对象 or null if not found.
*/
@SuppressWarnings("unchecked")
public T findUniqueBy(String propertyName, Object value) {
Assert.hasText(propertyName);
return (T) createCriteria(Restrictions.eq(propertyName, value)).uniqueResult();
}
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
@SuppressWarnings("unchecked")
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
Assert.notNull(criteria);
Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
CriteriaImpl impl = (CriteriaImpl) criteria;
// 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
Projection projection = impl.getProjection();
List<CriteriaImpl.OrderEntry> orderEntries;
try {
orderEntries = (List) BeanUtils.forceGetProperty(impl, "orderEntries");
BeanUtils.forceSetProperty(impl, "orderEntries", new ArrayList());
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
}
// 执行查询
int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
// 将之前的Projection和OrderBy条件重新设回去
criteria.setProjection(projection);
if (projection == null) {
criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
try {
BeanUtils.forceSetProperty(impl, "orderEntries", orderEntries);
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
}
// 返回分页对象
if (totalCount < 1)
return new Page();
int startIndex = Page.getStartOfPage(pageNo, pageSize);;
List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, Criterion... criterions) {
Criteria criteria = createCriteria(criterions);
return pagedQuery(criteria, pageNo, pageSize);
}
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(int pageNo, int pageSize, String orderBy, boolean isAsc,
Criterion... criterions) {
Criteria criteria = createCriteria(orderBy, isAsc, criterions);
return pagedQuery(criteria, pageNo, pageSize);
}
/**
* 判断对象某些属性的值在数据库中是否唯一.
*
* @param uniquePropertyNames 在POJO里不能重复的属性列表,以逗号分割 如"name,loginid,password"
*/
public boolean isUnique(T entity, String uniquePropertyNames) {
Assert.hasText(uniquePropertyNames);
Criteria criteria = createCriteria().setProjection(Projections.rowCount());
String[] nameList = uniquePropertyNames.split(",");
try {
// 循环加入唯一列
for (String name : nameList) {
criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));
}
// 以下代码为了如果是update的情况,排除entity自身.
String idName = getIdName(getEntityClass());
// 取得entity的主键值
PK id = getId(getEntityClass(), entity);
// 如果id!=null,说明对象已存在,该操作为update,加入排除自身的判断
if (id != null)
criteria.add(Restrictions.not(Restrictions.eq(idName, id)));
} catch (Exception e) {
ReflectionUtils.handleReflectionException(e);
}
return (Integer) criteria.uniqueResult() == 0;
}
/**
* 取得对象的主键值,辅助函数.
*/
@SuppressWarnings("unchecked")
public PK getId(Class<T> entityClass, T entity) throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException {
Assert.notNull(entity);
Assert.notNull(entityClass);
return (PK) PropertyUtils.getProperty(entity, getIdName(entityClass));
}
/**
* 取得对象的主键名,辅助函数.
*/
public String getIdName(Class<T> clazz) {
Assert.notNull(clazz);
ClassMetadata meta = getSessionFactory().getClassMetadata(clazz);
Assert.notNull(meta, "Class " + clazz + " not define in hibernate session factory.");
String idName = meta.getIdentifierPropertyName();
Assert.hasText(idName, clazz.getSimpleName() + " has no identifier property define.");
return idName;
}
}
IEntityDao.java
package com.hibernate.dao.extend;
import java.io.Serializable;
import java.util.List;
/**
* 针对单个Entity对象的CRUD操作定义.
*/
public interface IEntityDao<T,PK extends Serializable> {
T get(PK id);
List<T> getAll();
void save(T entity);
void remove(T entity);
void removeById(PK id);
void update(T entity);
/**
* 获取Entity对象的主键名.
*/
String getIdName(Class<T> clazz);
}
HibernateGenericDao.java
/**
*
*/
package com.hibernate.dao.generic;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hibernate.Query;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import com.hibernate.dao.support.Page;
/**
* 继承自spring的HibernateDaoSupport<br>
* 提供了和具体实体类无关的数据库操作,如分页函数和若干便捷查询方法
* @see HibernateDaoSupport
*/
public class HibernateGenericDao extends HibernateDaoSupport {
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
@SuppressWarnings("unchecked")
public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
Assert.hasText(hql);
Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
// Count查询
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
List countlist = getHibernateTemplate().find(countQueryString, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page();
// 实际查询返回分页对象
int startIndex = Page.getStartOfPage(pageNo, pageSize);
Query query = createQuery(hql, values);
List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* @param hql 查询sql
* @param start 分页从哪一条数据开始
* @param pageSize 每一个页面的大小
* @param values 查询条件
* @return page对象
*/
@SuppressWarnings("unchecked")
public Page dataQuery(String hql, int start, int pageSize, Object... values){
Assert.hasText(hql);
// Count查询
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
List countlist = getHibernateTemplate().find(countQueryString, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page();
// 实际查询返回分页对象
int startIndex = start;
Query query = createQuery(hql, values);
List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* 创建Query对象. 对于需要first,max,fetchsize,cache,cacheRegion等诸多设置的函数,可以在返回Query后自行设置.
* 留意可以连续设置,如下:
* <pre>
* dao.getQuery(hql).setMaxResult(100).setCacheable(true).list();
* </pre>
* 调用方式如下:
* <pre>
* dao.createQuery(hql)
* dao.createQuery(hql,arg0);
* dao.createQuery(hql,arg0,arg1);
* dao.createQuery(hql,new Object[arg0,arg1,arg2])
* </pre>
*
* @param values 可变参数.
*/
public Query createQuery(String hql, Object... values) {
Assert.hasText(hql);
Query query = getSession().createQuery(hql);
for (int i = 0; i < values.length; i++) {
query.setParameter(i, values[i]);
}
return query;
}
/**
* 根据hql查询,直接使用HibernateTemplate的find函数.
* @param values 可变参数
*/
@SuppressWarnings("unchecked")
public List find(String hql, Object... values) {
Assert.hasText(hql);
return getHibernateTemplate().find(hql, values);
}
/**
* 执行一些必须的sql语句把内存中的对象同步到jdbc的链接中
*/
public void flush() {
getHibernateTemplate().flush();
}
/**
* 清除所有对象缓存
*/
public void clear() {
getHibernateTemplate().clear();
}
/**
* 执行本地sql语句获得标量数值列表
*/
@SuppressWarnings("unchecked")
public List executeNativeSql(String sql){
return getSession().createSQLQuery(sql).list();
}
/**
* 去除hql的select 子句,未考虑union的情况,用于pagedQuery.
*/
private static String removeSelect(String hql) {
Assert.hasText(hql);
int beginPos = hql.toLowerCase().indexOf("from");
Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
return hql.substring(beginPos);
}
/**
* 去除hql的orderby 子句,用于pagedQuery.
*/
private static String removeOrders(String hql) {
Assert.hasText(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();
}
}
com.hibernate.dao.support下的3个类和如下的一致:
http://blog.csdn.net/tom_221x/archive/2008/12/05/3453312.aspx
相关文章推荐
- 改进版的hibernate泛型dao(依赖spring)
- Hibernate泛型Dao(依赖spring)
- 使用 Hibernate 和 Spring AOP 构建泛型类型安全的 DAO
- 不要重复DAO!使用Hibernate 和Spring AOP 构建泛型类型安全的DAO
- spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持
- Struts2、Hibernate、Spring整合的泛型DAO,以及通用的分页技术
- Struts2、Hibernate、Spring整合的泛型DAO,以及通用的分页技术
- Hibernate泛型DAO(结合spring模板支持)
- 不要重复DAO!使用Hibernate 和Spring AOP 构建泛型类型安全的DAO
- spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持
- 【DAO】不要重复 DAO---使用 Hibernate 和 Spring AOP 构建泛型类型安全的 DAO
- 虚拟数据层:Struts2、Hibernate、Spring整合的泛型DAO
- Struts2、Hibernate、Spring整合的泛型DAO Version 2010.9.27
- 不要重复 DAO! 使用 Hibernate 和 Spring AOP 构建泛型类型安全的 DAO
- 虚拟数据层 Struts2、Hibernate、Spring整合的泛型DAO Version 2010.9.27
- 使用 Hibernate 和 Spring AOP 构建泛型类型安全的 DAO
- spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持
- spring hibernate注解实现泛型dao
- spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持
- spring2.5整合hibernate3.3的泛型Dao并加入spring jdbc的支持