在项目中用Hibernate的DetachedCriteria 离线查询时,遇到一个问题,就是不能获得DetachedCriteria 投影后的记录的总数。后来看了http://www.iteye.com/topic/14657中的文章,找到了解决办法。
HibernateTemplate还提供一种更加灵活的方式来操作数据库,通过这种方式可以完全使用Hibernate的操作方式。
HibernateTemplate的灵活访问方式是通过如下两个方法完成:
1, Object execute(HibernateCallback action)
2, List execute(HibernateCallback action)
,比如上面那个问题。
在没有投影的情况下,可以用来获得记录总数。
((Integer) getHibernateTemplate().findByCriteria(criteria .setProjection(Projections.rowCount())).get(0)).intValue();
但是如果带有投影的情况下,上面的方法就不行,就需要更灵活的方法,
public Integer getTotal( final DetachedCriteria detachedCriteria ) { return (Integer) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue(); criteria.setProjection(null); return totalCount; } }, true); }
上面的方法需要一个HibernateCallback的实例,HibernateCallback实例可在任何有效的Hibernate数据访问中使用。程序开发者通过HibernateCallback,可以完全使用Hibernate灵活的方式来访问数据库,解决Spring封装Hibernate后灵活性不足的缺陷。HibernateCallback是一个接口,该接口只有一个方法doInHibernate(org.hibernate.Session session),该方法只有一个参数Session。
通常,程序中采用实现HibernateCallback的匿名内部类来获取HibernateCallback的实例,方法doInHibernate的方法体就是Spring执行的持久化操作。
注意:方法 doInHibernate 方法内可以访问 Session ,该 Session 对象是绑定到该线程的 Session 实例。该方法内的持久层操作,与不使用 Spring 时的持久层操作完全相同。这保证对于复杂的持久层访问,依然可以使用 Hibernate 的访问方式。
简单的说,使用回调(HibernateCallback )可以得到session,但是用HebernateTemplate.getSession()同样可以得到;
两个是有区别的,HibernateCallback 回调封装了对异常和事务的处理。而直接获得HebernateTemplate.getSession(),你还有很多事要做。
-------------------------------------------------------分割线--------------------------------------------------------------------
如果第一次运行的时候没问题。
等你去拿第2页的时候,就提示说出现NullPointer。 发现是((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult())为Null, 也就是根本就拿不到表总数。
现在就需要先把 Projection 和 OrderBy 条件取出来,清空两者后,再来执行Count操作。最后再把原条件设置进去。
@SuppressWarnings("deprecation") public Integer getTotal( final DetachedCriteria detachedCriteria ) { return (Integer) getTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = detachedCriteria.getExecutableCriteria(session); //先把Projection和OrderBy条件取出来,清空两者来执行Count操作 CriteriaImpl impl = (CriteriaImpl) criteria; Projection projection = impl.getProjection(); int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue(); //将之前的Projection和OrderBy条件重新设回去 criteria.setProjection(projection); if (projection == null) { criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY); } return totalCount; } }, true); }