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

手动为HibernateDAO里面的DetachedCriteria的Projection擦屁股

阅读更多

无奈,寻找好的解决方法,把我现在擦屁股的现场记录下来。
我用GenericHibernateDAO,慢慢积累下来的,有这几个DetachedCriteria的方法:

public  List findByDetachedCriteriaByPage(
        
final  DetachedCriteria detachedCriteria,  final   int  pagesize,
        
final   int  pageno) {
        
return  getHibernateTemplate()
                   .findByCriteria(detachedCriteria, pagesize 
*  pageno, pagesize);
    }

int  getCountByDetachedCriteria(
        
final  DetachedCriteria detachedCriteria) {
        Integer count 
=  (Integer) getHibernateTemplate().execute( new  HibernateCallback() {
                    
public  Object doInHibernate(Session session)
                        
throws  HibernateException {
                        Criteria criteria 
=  detachedCriteria.getExecutableCriteria(session);

                        
return  criteria.setProjection(Projections.rowCount())
                                       .uniqueResult();
                    }
                }, 
true );

        detachedCriteria.setProjection(
null );

        
return  count.intValue();
    }
这是一对方法,经常一起用,一开始没有注意,后来发现有副作用。
生成一个DetachedCriteria,调用完getCountByDetachedCriteria以后再调用findByDetachedCriteriaByPage返回的结果居然是一个Integer……
原来getCountByDetachedCriteria方法里面对detachedCriteria.getExecutableCriteria(session)产生的criteria设定了Projection,这也影响到了DetachedCriteria本身,以后再用它作查询都回返回Projection的结果。
现在的解决方法是手动擦屁股,重新set Null。(我原先以为final关键字会保证detachedCriteria不被修改,后来发现只是引用不能修改,实例本身可以随便修改)请问大家,有什么更好的解决方案么,我决得复杂一点的话这个detachedCriteria如何能擦除回来?


Reply from BJUG Groups by whimet:
这个问题在javaeye上已经讨论过:http://www.hibernate.org.cn/viewtopic.php?t=14657
你这种情况还简单,若DetachedCriteria中包含排序设置就更不好办。

其实关键问题是DetachedCriteria.getExecutableCriteria返回的Criteria实例中已经包含了投影和排序信息,如果你­想先查总数,
就得先去掉这些信息;查完总数,再查实际数据时,又得加上这些信息。而Criteria可没提供对它改来改去的接口。

不过,仔细考察一下DetachedCriteria可以发现,它类似一种暂存了查询条件的值对象,通过与一个session对象结合生成
一个“可执行的”Criteria,相当于先执行session.createCriteria,然后把自己保存的条件设置进去。

既然如此,我干脆自己提供一个类似的类,暂存查询条件,与session结合生成executableCriteria;但我先提供给用户一个只包含
查询条件的Criteria实例,让用户先拿着它去查总数;然后再提供加入投影和排序信息的方法,让用户拿着它去查数据,不就解决问题了。

-------------- 示例代码:

MyDetachedCriteria dc =  
Criteria c 
= dc.getExecutableCriteria( session );       //这里的c只包含查询条件,不包括投影和排序 
c.setProjection( Projections.rowCount() ); 
Integer total 
= (Integer) c.uniqueResult();             //得到总数 
dc.fillProjectionSetting( c );          //把dc中保存的投影信息设置进去 
dc.fillOrdersSetting( c );          //把dc中保存的排序信息设置进去 
List data = c.list();                           //取回数据 


-------------- MyDetachedCriteria的代码: 
/** 
 * 单独的值对象,用于暂存与Criteria相关的查询条件,并可与Session结合生成一个可执行的Criteria<br> 
 * <br> 
 * 该类继承自DetachedCriteria只是为了保持接口兼容性,其实与DetachedCriteria没关系 <br> 
 * (之所以叫“Detached”,是指与Session脱离) 
 
*/ 
public class MyDetachedCriteria extends DetachedCriteria { 


        
private Class entityClass; 


        
private ArrayList criterions = new ArrayList(); 


        
private ArrayList orders = new ArrayList(); 


        
private Projection projection; 


        
/** 
         * 
@param entityClass 
         
*/ 
        
public MyDetachedCriteria( Class entityClass ) { 
                
super( entityClass.getName() ); 
                
this.entityClass = entityClass; 
        } 


        
/** 
         * 
@see org.hibernate.criterion.DetachedCriteria#add(org.hibernate.criterion.Criter­ion) 
         
*/ 
        
public DetachedCriteria add( Criterion criterion ) { 
                criterions.add( criterion ); 
                
return this
        } 


        
/** 
         * 
@see org.hibernate.criterion.DetachedCriteria#addOrder(org.hibernate.criterion.O­rder) 
         
*/ 
        
public DetachedCriteria addOrder( Order order ) { 
                orders.add( order ); 
                
return this
        } 


        
/** 
         * 
@see org.hibernate.criterion.DetachedCriteria#setProjection(org.hibernate.criter­ion.Projection) 
         
*/ 
        
public DetachedCriteria setProjection( Projection projection ) { 
                
this.projection = projection; 
                
return this
        } 


        
// --------------------------------------------------------------------------- 


        
/** 
         * 根据Session实例创建一个Criteria实例,并填充入此对象自身保存的条件后返回<br> 
         * 注意:返回的Criteria实例不含排序和投影信息,用户需要自己调用fillOrdersSetting、 
         * fillProjectionSetting填充入排序和投影信息 
         * 
         * 
@see org.hibernate.criterion.DetachedCriteria#getExecutableCriteria(org.hibernat­e.Session) 
         
*/ 
        
public Criteria getExecutableCriteria( Session session ) { 
                Criteria result 
= session.createCriteria( entityClass ); 


                
for ( Iterator i = criterions.iterator(); i.hasNext(); ) { 
                        Criterion criterion 
= ( Criterion ) i.next(); 
                        result.add( criterion ); 
                } 


                
return result; 
        } 


        
/** 
         * 填充入排序信息设置 
         * 
         * 
@param criteria 
         * 
@return 
         
*/ 
        
public Criteria fillOrdersSetting( Criteria criteria ) { 
                
for ( Iterator i = orders.iterator(); i.hasNext(); ) { 
                        Order order 
= ( Order ) i.next(); 
                        criteria.addOrder( order ); 
                } 


                
return criteria; 
        } 


        
/** 
         * 填充入投影信息设置 
         * 
         * 
@param criteria 
         * 
@return 
         
*/ 
        
public Criteria fillProjectionSetting( Criteria criteria ) { 
                criteria.setProjection( projection ); 
                
return criteria; 
        } 






Update 2006-6-6 20:52:
恩,谢谢诸位。想了想还是DetachedCriteria设计的目的和我想要的不一样。DetachedCriteria目前只是为了脱离session就可以构造,而并不是为了反复使用。
因为:1、它里面只包装了一个CriteriaImpl,所以实际上两者生命周期比较一致。而且每次getExecutableCriteria都直接返回这个CriteriaImpl,而不是重新创建,这就造成了容易被意外修改。 2、它没有提供与add对应的remove方法,这就造成它只能累积而不能擦拭(对于Order),用反射就太脏了。
whimet写的这个MyDetachedCriteria倒是可以解决问题,更符合我们想要复用DetachedCriteria的需求,不过我觉得调用起来接口上不太统一。Order和Projection一般不用复用,我想就可以不用实现DetachedCriteria接口,干脆修改GenericDAO的方法好了,写个接受List<Criteria>或者Criteria...的方法对应就可以了。反正觉得DetachedCriteria目前的实现是不如意,hack它吧……我就想提供remove这些Order和Projection的方法。
这里用反射解决了他遇到的Order的问题,大家可以参考,看来DetachedCriteria目前实现的还不够令人满意:
关于Hibernate的DetachedCriteria查询的addOrder问题的解决办法

分享到:
评论
1 楼 gauzeehom 2011-03-17  

相关推荐

    Hibernate - DetachedCriteria 的完整用法

    "Hibernate - DetachedCriteria 的完整用法" Hibernate 的 Criteria 和 DetachedCriteria 是两个不同的概念,虽然它们都是用于查询数据的,但它们在创建和使用上有所不同。 首先,Criteria 是在线的,需要通过 ...

    HibernateDao.java

    《深入解析HibernateDao.java》 在Java开发领域,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。本文将深入探讨`HibernateDao.java`这一关键组件,揭示其背后的原理与实践应用。 `...

    Hibernate 使用DetachedCriteria操作

    **Hibernate 框架及其DetachedCriteria操作详解** Hibernate 是一个强大的Java持久化框架,它极大地简化了数据库操作,使得开发者能够用面向对象的方式处理数据库事务。本篇将深入探讨Hibernate中的...

    HibernateDao 通用

    HibernateDao 是一种基于 Hibernate ORM(对象关系映射)框架的通用数据访问对象,它简化了对数据库的操作,提供了更高级别的抽象,使开发者能够更加专注于业务逻辑而不是底层的数据操作。在Java开发中,Hibernate...

    HibernateDao

    hibernateDao工具类

    hibernate dao 生成工具

    Hibernate DAO(Data Access Object)生成工具是用于自动化创建数据访问层对象的实用程序,它可以显著提高开发效率,尤其是在处理大量数据库交互的项目中。DAO模式是一种设计模式,它提供了对数据库操作的抽象,使得...

    使用代理实现Hibernate Dao层自动事务

    本文将深入探讨如何使用代理来实现Hibernate Dao层的自动事务管理,以提高代码的可维护性和事务处理的效率。 首先,理解Dao(Data Access Object)层的作用至关重要。Dao层是应用与数据库之间的一层抽象,它封装了...

    HibernateDAO的写法

    《深入理解HibernateDAO的写法》 在Java企业级开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。而HibernateDAO则是基于Hibernate进行数据访问的对象,是业务逻辑层和持久层之间...

    Hibernate DAO生成器

    Hibernate DAO生成器是专门为Hibernate框架设计的工具,能够自动生成与数据库表对应的DAO类。这些DAO类包含了根据Hibernate的配置文件自动创建的CRUD(Create、Read、Update、Delete)方法,使得开发者可以直接调用...

    Hibernate封装dao层

    在Java开发中,DAO(Data Access Object)层是用于与数据库进行交互的接口或抽象类,主要用于隔离业务逻辑...通过以上步骤,我们可以构建一个高效且易于维护的Hibernate DAO层,为Java应用程序提供稳定的数据访问支持。

    HibernateDao类

    开发HIBERNATE,只要继承此类.一切变得简单多了. 继承的DAO类可一行代码实行增,删,改. 另外也支持查询.分页查询. 在事务方面还不完善. 代码是我自己写的.资源分要使用5点. 但大家可以在下载后点评一下.这样5点的积分...

    Hibernate(24): 为什么用DetachedCriteria不能表连接地取数据?

    本篇文章将深入探讨为什么DetachedCriteria无法直接支持表连接查询,并提供一些替代方案。 首先,DetachedCriteria主要用于离线查询,即不在当前Session内执行的查询。它的主要优势在于可以预编译查询条件,延迟到...

    使用模式设计及java5新特性在HibernateDAO中的应用

    标题 "使用模式设计及java5新特性在HibernateDAO中的应用" 涉及到的是软件开发中的两个关键领域:设计模式和Java编程语言的新特性,特别是在数据访问对象(DAO)层如何结合使用它们。这篇文章可能详细阐述了如何利用...

    一个通用的Hibernate DAO

    - **含义**:此处的描述简略且不太清晰,但可以理解为这是关于一个通用Hibernate DAO的文本资料或文档。 - **作用**:提供了一个简单的文档说明,用于描述通用Hibernate DAO的设计思路和实现方法。 #### 三、标签:...

    Haha.Hibernate SprintSideExt 通用HibernateDAO

    Haha.Hibernate SprintSideExt 通用HibernateDAO 文章资源 详见:http://blog.csdn.net/lijun7788/article/details/6658847

    spring+hibernate DAO生成工具

    这是一个DAO代码生成工具,只需要配置好数据库连接信息,和按照你的需求配置要生成到的路径,运行BAT文件就会生成操作数据库的代码,可以完成增加,删除,修改,查询等操作,不需要写SQL语句,生成完全面向对象的代码....

    Hibernate 原生通用DAO

    在传统的Hibernate使用中,我们需要为每个实体类编写大量的CRUD(Create, Read, Update, Delete)方法,而使用原生通用DAO可以减少这部分重复工作,提高开发效率。 在设计原生通用DAO时,通常会包含以下核心功能: ...

Global site tag (gtag.js) - Google Analytics