Hibernate 更灵活的用法 HibernateCallback

在项目中用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);  
	 }      
 

你可能感兴趣的:(spring,Hibernate)