摘要:的离线查询对象用起来的确很是方便,但是其有一个缺陷通过条件表达式方法添加的条件会累加其实就是存入中的这样如果要执行不同的查询需要不同的查询条件时就需要分别创建不同的离线查询对象。
背景hibernate的离线查询对象DetachedCriteria用起来的确很是方便,但是其有一个缺陷:通过·add(条件表达式)方法添加的条件, 会累加, 其实就是存入list中的, 这样如果要执行不同的查询, 需要不同的查询条件时, 就需要分别创建不同的离线查询对象。
今天碰到的一个需求中, 一个Action中对同一张表连续查了三次, 每一次用了不同的离线查询对象. 感觉优点麻烦, 就想看看有没有对应的方法清除上次用过不想用的条件表达式. 结果发现并没有, 于是, 就自己通过暴力反射的技术, 写了一个小工具方法, 可以实现清除指定离线查询对象中的所有条件表达式。
通常我们在使用离线查询技术时, 会这么使用.
如查询BaseDict对象对应的表中dictTypeCode=006的记录.
// 创建离线查询对象 DetachedCriteria dc = DetachedCriteria.forClass(BaseDict.class); // 设置查询条件 dc.add(Restrictions.eq("dictTypeCode", "006")); // 利用hibernateTemplate模板根据离线对象查询数据 Listlist = (List ) getHibernateTemplate().findByCriteria(dc);
然而, 当我们需要再次查询BaseDict中dictTypeCode=009的记录时, 需要重新创建一个新的DetachedCriteria. 否则, 会将上次dictTypeCode=006的条件合并起来. 看下图:
源码分析DetachedCriteria dc = DetachedCriteria.forClass(BaseDict.class);
==> 调用构造
DetachedCriteria dc = DetachedCriteria.forClass(clazz.getName); // 通过类名构建对象
==>
CriteriaImpl(entityName, ...) // 创建Criteria的实现类
注意: 这是实现类会在离线查询对象dc名为"impl"属性中持有.
进入CriteriaImpl会发现, 原来我们add的所有查询条件会保存在一个叫做:"CriteriaEntries"的ArrayList中, 并且提供了对应公有方法, 返回该list的Iterator迭代器.
经过上述分析, 笔者就有思路了:
利用公有方法获取CriteriaEntries的迭代器, 通过遍历删除迭代器中每一个元素, 即实现了清空条件的目的.
直接简单粗暴, 再次反射, 将dc名为"impl"属性重置, 即new一个新的ArrayList赋给它.
代码实现 思路一: 获取迭代器, 遍历删除private void eraseCriteria(DetachedCriteria dc) { try { Field impl = dc.getClass().getDeclaredField("impl"); impl.setAccessible(true); // 得到实现类 CriteriaImpl cimpl = (CriteriaImpl) impl.get(dc); // 思路一: 遍历criterionEntries, 清空所有 // 利用实现类的公有方法获取迭代器 Iterator思路二: 直接重置CriteriaEntriescriterionEntryIterator = cimpl.iterateExpressionEntries(); while (criterionEntryIterator.hasNext()) { // 删除本元素 criterionEntryIterator.remove(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Log.end(); }
private void eraseCriteria(DetachedCriteria dc) { try { Field impl = dc.getClass().getDeclaredField("impl"); impl.setAccessible(true); // 得到实现类 CriteriaImpl cimpl = (CriteriaImpl) impl.get(dc); // 思路二: 再次反射, 直接将criterionEntries置空. // 获取criterionEntries属性 Field criterionEntries = cimpl.getClass().getDeclaredField("criterionEntries"); criterionEntries.setAccessible(true); // 重置条件list criterionEntries.set(cimpl, new ArrayList()); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Log.end(); }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70733.html
一:字典表 字典信息:在项目中可能会使用到,已经存在的一些信息。 例如,客户的级别:普通用户,vip用户... 客户的来源:网络营销,电话营销... 客户所属行业:电子商务,房地产... 客户的性别:男,女 在保存用户的时候,这些信息都是已经存在的,不应该让用户让用户来任意填写, 而是通过下拉列表来让用户选择。 这些已经存在的信息称之为字典信...
一:字典表 字典信息:在项目中可能会使用到,已经存在的一些信息。 例如,客户的级别:普通用户,vip用户... 客户的来源:网络营销,电话营销... 客户所属行业:电子商务,房地产... 客户的性别:男,女 在保存用户的时候,这些信息都是已经存在的,不应该让用户让用户来任意填写, 而是通过下拉列表来让用户选择。 这些已经存在的信息称之为字典信...
摘要:是的简称,运行环境,为的运行提供了所需的环境。分割字符串,返回分割后的字符串数组。当计算的值相同时,我们称之为冲突,的做法是用链表和红黑树存储相同的值的。迭代器取代了集合框架中的,迭代器允许调用者在迭代过程中移除元素。 Java基础1.JDK和JRE有什么区别? JDK 是java development kit的简称,java开发工具包,提供java的开发环境和运行环境。JRE 是j...
摘要:此时,我们不能在层使用因为它是和绑定的。可以解决这个问题,即在层,程序员使用来构造查询条件,然后将这个作为方法调用参数传递给业务层对象。而业务层对象获得之后,可以在范围内直接构造,进行查询。参考问题十二投影聚合和分组是的实例工厂。 问题九、Hibernate里面如何用Criteria 查询记录数 【问题描述】在工作中,有一个比较复杂的feature使用的是hibernate的Crite...
阅读 1220·2021-09-02 13:36
阅读 2692·2019-08-30 15:44
阅读 2945·2019-08-29 15:04
阅读 3161·2019-08-26 13:40
阅读 3623·2019-08-26 13:37
阅读 1155·2019-08-26 12:22
阅读 972·2019-08-26 11:36
阅读 1189·2019-08-26 10:41