前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hibernate中executeUpdate的缓存问题

hibernate中executeUpdate的缓存问题

作者头像
全栈程序员站长
发布2022-11-01 15:47:59
6960
发布2022-11-01 15:47:59
举报
文章被收录于专栏:全栈程序员必看

介绍:

在开发一个更新部门编号的功能中遇到了一个由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 修正后的代码

代码语言:javascript
复制
	/**
	 * 调整部门编号
	 * @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准备执行的操作,而不是已经执行的操作

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍:
  • 问题描述:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档