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自动装箱拆箱与常量池
java 自动装箱与拆箱 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的 ...
- WndProc
主要用在拦截并处理系统消息和自定义消息. form窗体的一个重载方法. protected override void WndProc(ref Message m) { //拦截窗体最小化按钮消息 i ...
- SICP练习1.6的解答
cond和if有着同样的效果,为啥用cond实现的new-if不能用于一些函数? 我自己没想明白,在网上搜集了一下答案,部分解答觉得有道理,整理如下: 解答1: if和cond都是特定的求值顺序, 即 ...
- 平台播放声音(ext.js)
首先把需要的两个js文件放在public/core路径下 (文件已经上传到博客了) 音频文件放在文件一级目录 代码:JxCustom.loadAudio("wav/NG.wav") ...
- Qt信号与槽 如何写2个类,一个发送信号,一个接收并处理
题目: 假设要做2个类,一个类的值提供一个函数SetValue,当这个值发生变化时,假设>10就触发告警调用B的函数; ------------------------------------- ...
- MVC c# 调用sql的存储过程
var hid = new SqlParameter { ParameterName = "HistoryId", Value = history.Id, Direction = ...
- Socket 简易静态服务器 WPF MVVM模式(一)
整体代码下载 主要实现功能: Socket的简单应用 可修改IP和端口 显示来访信息 界面设计: 界面采用MVVM设计,很简陋. 前台的主要目的是 输入IP地址 输入端口 输入文件目录 开启监听和停止 ...
- mysql主从复制简单配置,满满的干货
mysql主从备份(复制)的基本原理 mysql支持单向.异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.mysql复制基于主服务器在二进制日志中跟踪所有对数据库的更改 ...
- 2、开始学习C++
1.创建C++程序 C++程序是严格区分大小写,Cout与COUT都是识别不出来的,下面给出了一段简单的C++程序. #include "stdafx.h" #include &l ...
- 3C - Youmu
(ans & arr[j]) == ans 保证高位已有值不失效. ((ans[j] >> (i - 1)) & 1) == 1 当前位为1,cnt++, cnt > ...