本站首页    管理页面    写新日志    退出


«October 2025»
1234
567891011
12131415161718
19202122232425
262728293031


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7643345
建立时间:2006年5月29日




[Hibernate]手动为HibernateDAO里面的DetachedCriteria的Projection擦屁股
软件技术,  电脑与网络

lhwork 发表于 2006/6/15 11:07:04

无奈,寻找好的解决方法,把我现在擦屁股的现场记录下来。我用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 = 500)this.width=500'> 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问题的解决办法


阅读全文(3118) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 1.043 second(s), page refreshed 144812429 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号