`
Hillen.chan
  • 浏览: 61062 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hibernate分页

阅读更多
这里想说的代码主要是泛型DAO层的应用与分页的写法.

分页,采用了hibernate的一些API来分页,这里同时采用了两种分页方式,CriteriaPage分页方式,适用于多表单时查询后分页用的,而第二种方式是采用Hql语句查询后分页的.代码如下:

CriteriaPage.java文件:
package org.mmc.commons; import java.util.ArrayList;
import java.util.List; import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.impl.CriteriaImpl.OrderEntry;
import org.mmc.utils.BeanUtils; /**
* 使用Hql查询的的分页查询类.
* 支持执行Count查询取得总记录条数
* 本类参考了springside项目的分页设计
*/
public class CriteriaPage { /**
* 得到一个PageInstance实例,.
*/
public static Page getPageInstance(Criteria criteria, int pageNo, int pageSize) {

return CriteriaPage.getPageInstanceByCount(criteria, pageNo, pageSize);
} /**
* 以查询Count的形式获取totalCount的函数
*/
protected static Page getPageInstanceByCount(Criteria criteria, int pageNo, int pageSize) {
CriteriaImpl impl = (CriteriaImpl) criteria; //先把Projection和OrderBy条件取出来,清空两者来执行Count操作
Projection projection = impl.getProjection();
List<OrderEntry> orderEntries;
try {
orderEntries = (List) BeanUtils.getPrivateProperty(impl, "orderEntries");
BeanUtils.setPrivateProperty(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.setPrivateProperty(impl, "orderEntries", orderEntries);
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
} return getPageResult(criteria, totalCount, pageNo, pageSize);
}

/**
* 取得totalCount后,根据pageNo和PageSize, 执行criteria的分页查询,取得Page变量
*/
private static Page getPageResult(Criteria criteria, int totalCount, int pageNo, int pageSize) {
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);
} }

HqlPage.java文件的代码
package org.mmc.commons; import java.util.List; import org.hibernate.Query; /**
* 使用Hql查询的的分页查询类.
* 支持执行getCount查询取得总记录条数
* 本类参考了springside项目的分页设计
*
* @author lighter
* @see org.mmc.commons.Page
*/
public class HqlPage { 
public static Page getPageInstanceByCount(Query query, int pageNo, int pageSize, int totalCount) {
return getPageResult(query, totalCount, pageNo, pageSize);
} private static Page getPageResult(Query q, int totalCount, int pageNo, int pageSize) {
if (totalCount < 1) return new Page();
int startIndex = Page.getStartOfPage(pageNo, pageSize);
List list = q.setFirstResult(startIndex).setMaxResults(pageSize).list(); return new Page(startIndex, totalCount, pageSize, list);
}
}

Page.java文件的源代码如下:
package org.mmc.commons; import java.util.ArrayList; /**
* 分页对象. 包含数据及分页信息.
* 
* @author lighter 天马行空
*/
public class Page implements java.io.Serializable {
/**
* 当前页第一条数据的位置,从0开始
*/
private int start; /**
* 每页的记录数
*/
private int pageSize = Constants.DEFAULT_PAGE_SIZE; /**
* 当前页中存放的记录
*/
private Object data; /**
* 总记录数
*/
private int totalCount; /**
* 构造方法,只构造空页
*/
public Page() {
this(0, 0, Constants.DEFAULT_PAGE_SIZE, new ArrayList());
} /**
* 默认构造方法
* 
* @param start
* 本页数据在数据库中的起始位置
* @param totalSize
* 数据库中总记录条数
* @param pageSize
* 本页容量
* @param data
* 本页包含的数据
*/
public Page(int start, int totalSize, int pageSize, Object data) {
this.pageSize = pageSize;
this.start = start;
this.totalCount = totalSize;
this.data = data;
} /**
* 取数据库中包含的总记录数
*/
public int getTotalCount() {
return this.totalCount;
} /**
* 取总页数
*/
public int getTotalPageCount() {
if (totalCount % pageSize == 0)
return totalCount / pageSize;
else
return totalCount / pageSize + 1;
} /**
* 取每页数据容量
*/
public int getPageSize() {
return pageSize;
} /**
* 当前页中的记录
*/
public Object getResult() {
return data;
} /**
* 取当前页码,页码从1开始
*/
public int getCurrentPageNo() {
return (start / pageSize) + 1;
} /**
* 是否有下一页
*/
public boolean hasNextPage() {
return (this.getCurrentPageNo() < this.getTotalPageCount() - 1);
} /**
* 是否有上一页
*/
public boolean hasPreviousPage() {
return (this.getCurrentPageNo() > 1);
} /**
* 获取任一页第一条数据的位置,每页条数使用默认值
* 关键字设为pretected
*/
protected static int getStartOfPage(int pageNo) {
return getStartOfPage(pageNo, Constants.DEFAULT_PAGE_SIZE);
} /**
* 获取任一页第一条数据的位置,startIndex从0开始
* 关键字设为pretected
*/
protected static int getStartOfPage(int pageNo, int pageSize) {
return (pageNo - 1) * pageSize;
}
}


分页的改造已经完成,现在重构一下DAO层的写法,利用了spring对hibernate支持的一些的API.
DAO层:
AbstractHibernateDao.java的源代码
package org.mmc.dao; import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.mmc.utils.GenericsUtils; import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set; /**
* 纯Hibernate Entity DAO基类.
* 通过泛型,子类无需扩展任何函数即拥有完整的CRUD操作.
*
*/
abstract public class AbstractHibernateDao<T> extends HibernateDaoSupport { protected Log logger = LogFactory.getLog(getClass()); /**
* Dao所管理的Entity类型.
*/
protected Class<T> entityClass; /**
* 取得entityClass的函数.
* JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重新实现此函数达到相同效果。
*/
protected Class getEntityClass() {
return entityClass;
} /**
* 在构造函数中将泛型T.class赋给entityClass
*/
public AbstractHibernateDao() {
entityClass = GenericsUtils.getGenericClass(getClass());
} public T get(Serializable id) {
T o = (T) getHibernateTemplate().get(getEntityClass(), id);
if (o == null)
throw new ObjectRetrievalFailureException(getEntityClass(), id);
return o;
} public List<T> getAll() {
return getHibernateTemplate().loadAll(getEntityClass());
} public void save(Object o) {
getHibernateTemplate().saveOrUpdate(o);
} public void removeById(Serializable id) {
remove(get(id));
} public void remove(Object o) {
getHibernateTemplate().delete(o);
} public List<T> find(String hsql, Object... values) {
if (values.length == 0)
return getHibernateTemplate().find(hsql);
else
return getHibernateTemplate().find(hsql, values);
} /**
* 根据属性名和属性值查询对象.
*
* @return 符合条件的唯一对象
*/
public T findUniqueBy(String name, Object value) {
Criteria criteria = getSession().createCriteria(getEntityClass());
criteria.add(Restrictions.eq(name, value));
return (T) criteria.uniqueResult();
} /**
* 根据属性名和属性值查询对象.
*
* @return 符合条件的对象列表
*/
public List<T> findBy(String name, Object value) {
Assert.hasText(name);
Criteria criteria = getSession().createCriteria(getEntityClass());
criteria.add(Restrictions.eq(name, value));
return criteria.list();
} /**
* 根据属性名和属性值以Like AnyWhere方式查询对象.
*/
public List<T> findByLike(String name, String value) {
Assert.hasText(name);
Criteria criteria = getSession().createCriteria(getEntityClass());
criteria.add(Restrictions.like(name, value, MatchMode.ANYWHERE));
return criteria.list();
} /**
* 根据Map中过滤条件进行查询.
*
* @param filter 过滤条件.
* @param criteriaSetup 将Map中条件转换为criteria的call back类
*/
public List<T> findBy(Map filter, CriteriaSetup criteriaSetup) {
Criteria criteria = getEntityCriteria();
if (!CollectionUtils.isEmpty(filter)) {
criteriaSetup.setup(criteria, filter);
}
return criteria.list();
} /**
* 函数作用同 {@link #findBy(Map,CriteriaSetup)}
* 如果不需要分页,子类可直接重载此函数.
*/
public List<T> findBy(Map filter) {
return findBy(filter, getDefaultCriteriaSetup());
} protected CriteriaSetup getDefaultCriteriaSetup() {
return new CriteriaSetup() {
public void setup(Criteria criteria, Map filter) {
if (filter != null && !filter.isEmpty()) {
Set keys = filter.keySet();
for (Object key : keys) {
String value = (String) filter.get(key);
if (StringUtils.isNotBlank(value))
criteria.add(Restrictions.eq((String) key, value));
}
}
}
};
} /**
* 取得Entity的Criteria.
*/
protected Criteria getEntityCriteria() {
return getSession().createCriteria(getEntityClass());
} /**
* 构造Criteria的排序条件默认函数.可供其他查询函数调用
*
* @param criteria Criteria实例.
* @param sortMap 排序条件.
* @param entity entity对象,用于使用反射来获取某些属性信息
*/
protected void sortCriteria(Criteria criteria, Map sortMap, Object entity) {
if (!sortMap.isEmpty()) {
for (Object o : sortMap.keySet()) {
String fieldName = o.toString();
String orderType = sortMap.get(fieldName).toString(); //处理嵌套属性如category.name,modify_user.id,暂时只处理一级嵌套
if (fieldName.indexOf(.) != -1) {
String alias = StringUtils.substringBefore(fieldName, ".");
String aliasType = alias;
try {
aliasType = PropertyUtils.getProperty(entity, alias).getClass().getSimpleName();
} catch (Exception e) {
logger.error("Get property" + alias + " error");
}
criteria.createAlias(aliasType, alias);
} if ("asc".equalsIgnoreCase(orderType)) {
criteria.addOrder(Order.asc(fieldName));
} else {
criteria.addOrder(Order.desc(fieldName));
}
}
}
} /**
* 判断对象某列的值在数据库中不存在重复
*
* @param names 在POJO里相对应的属性名,列组合时以逗号分割<br>
* 如"name,loginid,password"
*/
public boolean isNotUnique(Object entity, String names) {
Assert.hasText(names);
Criteria criteria = getSession().createCriteria(entity.getClass()).setProjection(Projections.rowCount());
String[] nameList = names.split(",");
try {
for (String name : nameList) {
criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));
} String keyName = getSessionFactory().getClassMetadata(entity.getClass()).getIdentifierPropertyName();
if (keyName != null) {
Object id = PropertyUtils.getProperty(entity, keyName);
//如果是update,排除自身
if (id != null)
criteria.add(Restrictions.not(Restrictions.eq(keyName, id)));
}
}
catch (Exception e) {
logger.error(e.getMessage());
return false;
}
return ((Integer) criteria.uniqueResult()) > 0;
}
}

再建一个文件:
BaseHibernateDao.java
package org.mmc.dao; import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.CriteriaSpecification;
import org.mmc.commons.CriteriaPage;
import org.mmc.commons.HqlPage;
import org.mmc.commons.Page;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; /**
* Hibernate Entity Dao基类.
* 扩展的分页函数,具体的分页代码在Page类中.
*
* @see AbstractHibernateDao
* @see HqlPage
* @see CriteriaPage
*/
abstract public class BaseHibernateDao<T> extends AbstractHibernateDao<T> {
/**
* 根据Map中过滤条件和分页参数进行分页查询.
*
* @param filterMap 过滤条件.
* @param pageNo 当前页码
* @param pageSize 每页显示记录数.
*/
public Page findBy(Map filterMap, int pageNo, int pageSize) {
return findBy(filterMap, null, pageNo, pageSize);
} /**
* 根据Map中过滤条件,排序条件和分页参数进行分页查询.
*
* @param filterMap 过滤条件.
* @param orderMap 排序条件.
* @param pageNo 当前页码
* @param pageSize 每页显示记录数.
*/
public Page findBy(Map filterMap, Map orderMap, int pageNo, int pageSize, CriteriaSetup criteriaSetup) {
Criteria criteria = getSession().createCriteria(getEntityClass()); if (!CollectionUtils.isEmpty(filterMap)) {
try {
criteriaSetup.setup(criteria, filterMap);
} catch (Exception e) {
}
} if (!CollectionUtils.isEmpty(orderMap))
sortCriteria(criteria, orderMap, null); criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); return pagedQuery(criteria, pageNo, pageSize);
} public Page findBy(Map filterMap, Map orderMap, int pageNo, int pageSize) {
return findBy(filterMap, orderMap, pageNo, pageSize, getDefaultCriteriaSetup());
} /**
* Criteria分页查询,采用了getCount模式
*/
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
return CriteriaPage.getPageInstance(criteria, pageNo, pageSize);
} /**
* HQL分页查询,可以指定具体的模式,
* 采用getCount方式,须在此层完成hsql的转换与查询。
* 注意参数Object...args的应用,可以在查询的设置查询条件用的(JDK5.0语法)
*/
public Page pagedQuery(String hql, int pageNo, int pageSize, Object... args) {
Assert.hasText(hql);
Query query = getSession().createQuery(hql);
for (int i = 0; i < args.length; i++) {
query.setParameter(i, args[i]);
}
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
List countlist = getHibernateTemplate().find(countQueryString, args);
int totalCount = (Integer) countlist.get(0);
return HqlPage.getPageInstanceByCount(query, pageNo, pageSize, totalCount);
} /**
* 去除select 子句,未考虑union的情况
*/
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);
} /**
* 去除orderby 子句
*/
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();
}
}
BaseHibernateDAO负责抽象一个Entity 的CRUD函数。 所有子类只要声明如下,即拥有如下函数:
public class UserDAO extends BaseHibernateDao<User> 
protected final Log logger 
public Object get(Serializable id) 
public List getAll() 
public void save(Object o) 
public void remove(Serializable id) 
public void remove(Object o) 
public List find(String hql) 
public List find(String hql,Object value) 
public List find(String hql,object[]) 
public Object findBy(String name,Object value) 
public List findAllBy(String name,Object value) 
public List findAllByLike(String name,Object value) 
public List findAllBy(Map filter)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics