博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用反射清空hibernate离线查询对象中的所有条件
阅读量:5820 次
发布时间:2019-06-18

本文共 2760 字,大约阅读时间需要 9 分钟。

hibernate的离线查询对象DetachedCriteria用起来的确很是方便,但是其有一个缺陷:通过·add(条件表达式)方法添加的条件, 会累加, 其实就是存入list中的, 这样如果要执行不同的查询, 需要不同的查询条件时, 就需要分别创建不同的离线查询对象。

今天碰到的一个需求中, 一个Action中对同一张表连续查了三次, 每一次用了不同的离线查询对象. 感觉优点麻烦, 就想看看有没有对应的方法清除上次用过不想用的条件表达式. 结果发现并没有, 于是, 就自己通过暴力反射的技术, 写了一个小工具方法, 可以实现清除指定离线查询对象中的所有条件表达式

背景

通常我们在使用离线查询技术时, 会这么使用.

如查询BaseDict对象对应的表中dictTypeCode=006的记录.

// 创建离线查询对象DetachedCriteria dc = DetachedCriteria.forClass(BaseDict.class);// 设置查询条件dc.add(Restrictions.eq("dictTypeCode", "006"));// 利用hibernateTemplate模板根据离线对象查询数据List
list = (List
) getHibernateTemplate().findByCriteria(dc);

然而, 当我们需要再次查询BaseDictdictTypeCode=009的记录时, 需要重新创建一个新的DetachedCriteria. 否则, 会将上次dictTypeCode=006的条件合并起来. 看下图:

clipboard.png

源码分析

DetachedCriteria dc = DetachedCriteria.forClass(BaseDict.class);

==> 调用构造
DetachedCriteria dc = DetachedCriteria.forClass(clazz.getName); // 通过类名构建对象
==>
CriteriaImpl(entityName, ...) // 创建Criteria的实现类
注意: 这是实现类会在离线查询对象dc名为'impl'属性中持有.

进入CriteriaImpl会发现, 原来我们add的所有查询条件会保存在一个叫做:'CriteriaEntries'的ArrayList中, 并且提供了对应公有方法, 返回该list的Iterator迭代器.

经过上述分析, 笔者就有思路了:

  1. 利用公有方法获取CriteriaEntries的迭代器, 通过遍历删除迭代器中每一个元素, 即实现了清空条件的目的.
  2. 直接简单粗暴, 再次反射, 将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
criterionEntryIterator = cimpl.iterateExpressionEntries(); while (criterionEntryIterator.hasNext()) { // 删除本元素 criterionEntryIterator.remove(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } Log.end(); }

思路二: 直接重置CriteriaEntries

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();            }

转载地址:http://myzdx.baihongyu.com/

你可能感兴趣的文章
influxdb入门——和mongodb一样可以动态增加字段
查看>>
我对大项目的看法(定义)
查看>>
phpmyadmin出现缺少mysqli扩展问题
查看>>
C#学习笔记——TCP通讯
查看>>
[转载]成为优秀程序员的10个有效方法
查看>>
SQL SERVER 与ACCESS、EXCEL的数据转换
查看>>
[Android Pro] Android 手机root 并 安装 BusyBox pro 和 Android Terminal Emulator
查看>>
认识javascript范围和作用域链
查看>>
C++中引用传递与指针传递的区别
查看>>
[Java基础] Java对象内存结构
查看>>
【原创】Matlab.NET混合编程技巧之直接调用Matlab内置函数
查看>>
ExtTree学习笔记(转载)
查看>>
算法-快速排序
查看>>
sqlserver-触发器-判断更新了哪个字段。
查看>>
PowerShell 脚本中的密码
查看>>
Atitit.jquery 版本号新特性attilax总结
查看>>
Extjs4.10Model模型具体解释
查看>>
【Git】Git与GitHub 入门【转】
查看>>
url传递中文的解决方案
查看>>
dump_stack 实现分析【转】
查看>>