java 离线查询对象_hibernate离线查询DetachedCriteria清除上次的查询条件

1 原例概述

别名重复问题之后,我们还需要解决的问题就是:

如何清除hibernate的上次查询条件,如果不清除,将会导致上次的查询条件和下次的查询条件合并到了一起。

36f6d5716adee17de1417f17fb0facb4.png

上次的查询条件和本次的查询条件合并到了一起。

解决之前的代码如下:

public String pageQuery() throwsException {

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"});returnNONE;

}

第二次执行上面的代码将不会得到结果:原因是前一次的查询条件和本次的查询条件合并了。

这个我们可以通过发送的sql语句看出来

069d21345467868abebea3be91309a83.png

解决上述问题原理就是:本次查询之前需要清除hibernate之前的离线查询条件。

下面我们来看看上述问题的出现原因和解决办法。

2 背景

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

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

//创建离线查询对象

DetachedCriteria dc = DetachedCriteria.forClass(BaseDict.class);//设置查询条件

dc.add(Restrictions.eq("dictTypeCode", "006"));//利用hibernateTemplate模板根据离线对象查询数据

List list = (List) getHibernateTemplate().findByCriteria(dc);

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

16da51e34e4f16d7ab47b5498cb4d473.png

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 voideraseCriteria(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 voideraseCriteria(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, newArrayList());

}catch(NoSuchFieldException e) {

e.printStackTrace();

}catch(IllegalAccessException e) {

e.printStackTrace();

}

Log.end();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值