hibernate中executeUpdate的缓存问题

hibernate中executeUpdate的缓存问题解决hibernate批量更新时的缓存问题

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

介绍:

在开发一个更新部门编号的功能中遇到了一个由hibernate缓存导致的问题,后来发现是由于hibernate的缓存机制所导致,这里记录了一下这个问题及其分析解决方法。

环境介绍:spring3 + hibernate3

问题描述:

在做单元测试的时候,有一个调整部门排序的方法adjustDeptOrder(String deptid,String targetDeptid)始终无法通过测试

1 adjustDeptOrder 方法逻辑描述 :

1.记录插入位置

2.把插入位置以后的部门排序号+1。{使用批量更新hibernate中的executeUpdate() }

3.把插入的部门排序更新成插入位置的序号。{使用hibernate.update()方法}

主要方法1:

/**
	 * 调整部门排序
	 * @param deptid
	 * @param targetDeptid
	 * @param shift
	 */
	public void adjustDeptOrder(String deptid,String targetDeptid){
		
		Dept dept = this.deptDAO.findById(deptid);
		Dept targetDept = this.deptDAO.findById(targetDeptid);
		int targetOrder = targetDept.getOrderno();
		int count = deptDAO.updateDeptOrderNo(""+targetOrder);
		dept.setOrderno(targetOrder);
		deptDAO.update(dept);
	}

主要方法2:

/**
	 * 调整部门编号
	 * @return
	 */
	public int updateDeptOrderNo(String orderNo){  
		//log.info("================== clear 0.1");
        Map
   
     params = new HashMap();    
        
        StringBuffer sb=new StringBuffer();
        sb.append("update Dept t set t.orderno = t.orderno+1 where t.orderno >="+orderNo);  
        int count = getSession().createQuery(sb.toString()).executeUpdate();   
 
        return count;    
    } 

   

测试前数据状态

1 调整部门排序号之前的情况

     部门1   1

     部门2   2 

     部门3   3

 期待的结果

如果把“部门3”插入至”部门1”之前的话,程序执行的步骤

1 先记录”部门1″ 的序号 “1”

2 然后更新部门1、2、3的序号

     部门1   2

     部门2   3 

     部门3   4

3 把部门3的序号更新为 1 (也是最终期待的输出结果)

     部门3   1

     部门1   2 

     部门2   3

实际结果

     部门1   1

     部门2   2 

     部门3   1

     备注:在执行了adjustDeptOrder以后,数据库中的记录期待的情况相同,但是在确却未能通过junit的测试,通过debug以后发现部门排序情况是这样的。

问题原因分析:

1 初步分析

首先怀疑执行executeUpdate方法后不会更新到缓存到hibernate的一级缓存中去,所以junit测试的时候拿到的还是原来的缓存对象。

2 方法执行调试:

1 executeUpdate被执行时尽管后台也有响应的hql输出,但是此时调用获取部门列表,查看返回的部门列表,排序属性还是原来的,所以executeUpdate不会更新hibernate的缓存中对象的,这也情有可原因为executeUpdate操作是可能更新海量数据的。

2 测试用例中获取单个部门id的方法,并没有输出sql语句,所以肯定是从缓存中获取对象的,所以你能理解部门1、部门2的排序还是1、2了吧 。

备注:尽管缓存中的数据属性未及时更新,但是后台数据库是已经是正常的了,所以如果你不做单元测试的话压根就不会知道这里还有这么个猫腻。但是你想想如果这些缓存对象的属性如果继续被其他业务所用,后果是不是很严重。

3 结论

最后结合测试完成以后的数据库的部门排序确发生变化可以推断出,应该就是hibernate的缓存的问题。通过网上的搜索发现可以通过调用session.clear方法,手动清除一级缓存中的内容来解决这一问题。

4 修正后的代码

	/**
	 * 调整部门编号
	 * @return
	 */
		public int updateDeptOrderNo(String orderNo){  
		//log.info("================== clear 0.1");
      		Map<String,Object> params = new HashMap();    
        
        	StringBuffer sb=new StringBuffer();
        	sb.append("update Dept t set t.orderno = t.orderno+1 where t.orderno >="+orderNo);  
        	int count = getSession().createQuery(sb.toString()).executeUpdate();    
        	this.getSession().clear(); //
        	return count;    
    	} 

备注:

1 在调试当中还发现一个clear的用法,就是在调用update、add之后 、调用clear后,缓存中的对象时不会更新到数据库中去的。

2 在控制台中输出了sql语句 应该是hibernate准备执行的操作,而不是已经执行的操作


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/179898.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • matlab解常微分方程组数值解法(二元常微分方程组的解法)

    上篇博客介绍了Matlab求解常微分方程组解析解的方法:博客地址微分方程组复杂时,无法求出解析解时,就需要求其数值解,这里来介绍。以下内容按照Matlab官方文档提供的方程来展开(提议多看官方文档)介绍一下核心函数ode45()一般形式:[t,y]=ode45(odefun,tspan,y0) 其中tspan=[t0tf]功能介绍:求微分方程组y′=f(t,y)从t0…

  • es6之Promise是什么「建议收藏」

    es6之Promise是什么「建议收藏」Promise的含义Promise是一个容器,内部保存着某个未来才会结束的事件(通常是一个异步操作)的结果。Promise也是一个对象,可以通过这个对象获取异步操作的消息。Promise的特点:对象的状态不受外部影响,只有异步操作的结果才能决定状态。一共有三种状态:pending(进行中)、fulfilled(成功的)和rejected(失败的)。对象的状态发生改变后,不会再变化,并且随时可以得到这个结果。对象的状态改变只有两种情况:pending=》fulfilled,pending=》reje

  • pycharm安装使用教程_vcenter安装

    pycharm安装使用教程_vcenter安装1.PyCharm介绍PyCharm是一种PythonIDE,其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如,调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外,该IDE提供了一些高级功能,以用于支持Django框架下的专业Web开发。同时支持GoogleAppEngine,更酷的是,PyCharm支持IronPython!这些功能在先进代码分析程序的支持下,使PyCharm成为Python专业开发人员和刚起步人员使

  • WinHttp应用demo

    WinHttp应用demo#include#include#include#pragmacomment(lib,”winhttp”)structcallback_param_t{HINTERNEThInet;DWORDdwErrCert;};staticVOIDCALLBACKSyncCallback(HINTERNET,DWORD_PTR,DWORD,

  • webstorm2021 激活码 online【2021免费激活】

    (webstorm2021 激活码 online)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1…

  • gcc的编译命令_cmake 编译

    gcc的编译命令_cmake 编译GCC编译命令                    —————-加入新公司后,基本上是一键式打包脚本,对于GCC基本上快忘了,重新拾起。GCC命令提供了非常多的命令选项,但并不是所有都要熟悉,初学时掌握几个常用的就可以了,到后面再慢慢学习其它选项,免得因选项太多而打击了学习的信心。一.常用编译命令选项假设源程序文件名为test.c。1…

    2022年10月13日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号