hibernate离线查询DetachedCriteria清除上次的查询条件
1 原例概述
别名重复问题之后,我们还需要解决的问题就是:
如何清除hibernate的上次查询条件,如果不清除,将会导致上次的查询条件和下次的查询条件合并到了一起。
上次的查询条件和本次的查询条件合并到了一起。
解决之前的代码如下:
- public String pageQuery() throws Exception {
- DetachedCriteria dc = pageBean.getDetachedCriteria();
- //每一次分页查询的时候应该先清除之前的条件
- // 动态添加过滤条件
- String addresskey = model.getAddresskey();
- if (StringUtils.isNotBlank(addresskey)) {
- // 添加过滤条件,根据地址关键字模糊查询
- dc.add(Restrictions.like("addresskey", "%" + addresskey + "%"));
- }
- Region region = model.getRegion();
- if (region != null) {
- String province = region.getProvince();
- String city = region.getCity();
- String district = region.getDistrict();
- //创建别名之前需要判断别名是否存在。
- boolean existAlias = existAlias(dc,null,"r");
- if(!existAlias){//不存在就创建
- dc.createAlias("region", "r");
- }
- if (StringUtils.isNotBlank(province)) {
- // 添加过滤条件,根据省份模糊查询-----多表关联查询,使用别名方式实现
- // 参数一:分区对象中关联的区域对象属性名称
- // 参数二:别名,可以任意
- dc.add(Restrictions.like("r.province", "%" + province + "%"));
- }
- if (StringUtils.isNotBlank(city)) {
- // 添加过滤条件,根据市模糊查询-----多表关联查询,使用别名方式实现
- // 参数一:分区对象中关联的区域对象属性名称
- // 参数二:别名,可以任意
- dc.add(Restrictions.like("r.city", "%" + city + "%"));
- }
- if (StringUtils.isNotBlank(district)) {
- // 添加过滤条件,根据区模糊查询-----多表关联查询,使用别名方式实现
- // 参数一:分区对象中关联的区域对象属性名称
- // 参数二:别名,可以任意
- dc.add(Restrictions.like("r.district", "%" + district + "%"));
- }
- }
- subareaService.pageQuery(pageBean);
- this.java2Json(pageBean,
- new String[] { "currentPage", "detachedCriteria", "pageSize", "decidedzone", "subareas" });
- return NONE;
- }
第二次执行上面的代码将不会得到结果:原因是前一次的查询条件和本次的查询条件合并了。
这个我们可以通过发送的sql语句看出来
解决上述问题原理就是:本次查询之前需要清除hibernate之前的离线查询条件。
下面我们来看看上述问题的出现原因和解决办法。
2 背景
通常我们在使用离线查询技术时, 会这么使用.
如查询BaseDict
对象对应的表中dictTypeCode=006
的记录.
- // 创建离线查询对象
- DetachedCriteria dc = DetachedCriteria.forClass(BaseDict.class);
- // 设置查询条件
- dc.add(Restrictions.eq("dictTypeCode", "006"));
- // 利用hibernateTemplate模板根据离线对象查询数据
- List<BaseDict> list = (List<BaseDict>) getHibernateTemplate().findByCriteria(dc);
然而, 当我们需要再次查询BaseDict
中dictTypeCode=009
的记录时, 需要重新创建一个新的DetachedCriteria. 否则, 会将上次dictTypeCode=006
的条件合并起来. 看下图:
3 源码分析
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
赋给它.
4 解决上述问题的代码实现
思路一: 获取迭代器, 遍历删除
- private void eraseCriteria(DetachedCriteria dc) {
- try {
- Field impl = dc.getClass().getDeclaredField("impl");
- impl.setAccessible(true);
- // 得到实现类
- CriteriaImpl cimpl = (CriteriaImpl) impl.get(dc);
- // 思路一: 遍历criterionEntries, 清空所有
- // 利用实现类的公有方法获取迭代器
- Iterator<CriteriaImpl.CriterionEntry> 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();
- }
hibernate离线查询DetachedCriteria清除上次的查询条件的更多相关文章
- Hibernate框架进阶(下篇)之查询
导读 Hibernate进阶篇分为上中下三篇,本文为最后一篇,主要内容是Hibernate框架的查询,主要包括hql语句查询,criteria查询以及查询策略的选择. 知识框架 Hibernate查询 ...
- Hibernate的条件查询的几种方式+查询所有的记录
条件查询 . 第一种,用?占位符,如: //登录(用?占位符) public List<UserPO> LoginUser(UserPO up)throws Exception{ Sess ...
- Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o
Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o 1. Criteria,,Criterion ,, 1 <2. 主要的对象黑头配置磊 ...
- Atitit.Hibernate于Criteria 使用汇总and 关系查询 and 按照子对象查询 o9o
Atitit.Hibernate于Criteria 使用总结and 关联查询 and 依照子对象查询 o9o 1. Criteria,,Criterion ,, 1 <2. 基本的对象黑头配置磊 ...
- Hibernate第十篇【Hibernate查询详解、分页查询】
前言 在Hibernate的第二篇中只是简单地说了Hibernate的几种查询方式-.到目前为止,我们都是使用一些简单的主键查询阿-使用HQL查询所有的数据-.本博文主要讲解Hibernate的查询操 ...
- 分页查询时,使用cookie保存上次的查询条件。jQuery实现方法以及中间遇到的坑
今天做分页查询时需要在跳转页面时保存上次查询的条件,如下: 实现的大致思路就是用cookie本地保存. 其中需要用到jQuery.Cookie插件. 使用方法很简单: 存数据:$.cookie(“ke ...
- hibernate框架学习笔记7:HQL查询、Criteria查询简介
HQL查询:hibernate独有的查询语言 适用于不复杂的多表查询 示例: 实体类: package domain; public class Customer { private Long cus ...
- Hibernate(十四):HQL查询(三)
背景 基于上两章节<Hibernate(十二):HQL查询(一)>.<Hibernate(十三):HQL查询(二)>,已经学习了一部分关于HQL的用法: HQL带参数查询 HQ ...
- Hibernate(十二):HQL查询(一)
概述 Hibernate提供了以下几种检索对象的方式 1)导航对象图检索方式:根据已经加载的对象导航到其他对象: 2)OID检索方式:按照对象的OID来检索对象: 3)HQL检索方式:使用面向对象的H ...
随机推荐
- 关于JAVA数组的几点注意事项与一些低级错误
1.数组不是集合,它只能保存同种类型的多个原始类型或者对象的引用.数组保存的仅仅是对象的引用,而不是对象本身. 2.数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型 ...
- 【C#】CLR内存那点事(初级)
最近回头看了一下书,对内存的理解又有新的认识.我所关注的内存里面说没有寄存器的,所以我关注的只有 托管堆(heap),栈(stack), 字符串常量池(string是一个很特殊的对象) 首先我们看两个 ...
- 【C#】MVC+EF+LINQ 综合小项目
第一,创建数据库 create table category(id int primary key,name nvarchar(20)) create table news(id int primar ...
- asp.netcore+jenkins+docker+svn+centos7.2 持续集成,每天凌晨获取最新代码打包发布
运行环境: centos7.2服务器或则虚拟机 可以是腾讯云也可以是内网服务器,(如果是内网服务器需要用frp做内网穿透,这样才可以通过外网访问该服务器) svnserver 来托管代码 一.安装je ...
- 《C#多线程编程实战》2.4 SemaphoreSlim
这个简单多了. 理解也是很好理解. 比上一个mutex好理解多了. 这个SemaphoreSlim是干什么呢? 就是限制线程的来访问. 好比说一次只有两个,一次只有三个 这样的线程来访问资源. 有点 ...
- 进阶Kotlin-常见关键字
常见Kotlin 的关键字 一些常见的语法,我没有写注释. 前面基础的kotlin语法已经弄完了. 现在是高阶kotlin的语法啊. 包括,面向对象,lambad等. 其中面向对象的三大特点:封装 ...
- php代码审计2全局变量和超全局变量
全局变量:就是在函数外面定义的变量,不能在函数中直接使用,因为它的作用域不会到函数内部,所以在函数内部使用的时候尝尝看到类似global $a; 超全局变量:在所有脚本都有效,所以,在函数可以直接使用 ...
- Squid系统服务脚本
#!/bin/bash # chkconfig: - 90 25 #其中-的意思是所有运行级别 # config: /etc/squid.conf # pidfile: /usr/local/squi ...
- Python中实现简单的插件框架
在系统设计中,经常我们希望设计一套插件机制,在不修改程序主体情况下,动态去加载附能. 我设想的插件系统: 1.通过类来实现 2.自动查找和导入 我们假设需要实现一个简单的插件系统,插件可以接收一个参数 ...
- 条目十五《注意strng实现的多样性》
条目十五<注意strng实现的多样性> 下面以一个打印string空对象的大小切入本条目: #include #include using namespace std; int main( ...