hibernate中executeUpdate的缓存问题
来源:互联网 发布:通联数据网站 编辑:程序博客网 时间:2024/06/05 14:03
介绍:
在开发一个更新部门编号的功能中遇到了一个由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"); Mapparams = 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准备执行的操作,而不是已经执行的操作
0 0
- hibernate中executeUpdate的缓存问题
- Hibernate中缓存的问题
- Hibernate中CreateSQLQuery的executeUpdate(sql)方法的返回值
- Hibernate中execute、executeQuery和executeUpdate之间的区别
- Hibernate中execute、executeQuery跟executeUpdate之间的区别
- hibernate缓存的问题
- Hibernate的缓存问题
- hibernate的缓存问题
- hibernate缓存的问题
- 关于hibernate缓存的问题
- 关于hibernate缓存的问题
- 奇葩!PreparedStatement.executeUpdate执行之后的问题
- java中execute executeUpdate executeQuery的区别
- jdbc 中 excute executeUpdate的用法作用
- hibernate 的一级缓存的相关问题
- 详解hibernate的cache缓存问题
- hibernate刷新数据时的缓存问题
- 简单总结一下Hibernate的缓存问题
- notepad+无法输入中文解决办法
- struts2 类型转换
- ZOJ Monthly, January 2014(2014省赛练习)
- 数据库的创建,用户,及权限分配---MYSQL技术之路(一)
- 在linux下安装并操作tomcat
- hibernate中executeUpdate的缓存问题
- Java的内存回收机制
- java连接JDBC的控制步骤
- 概率与统计试题
- db2 分区数据库详解
- hdu 2093(简单模拟)
- delphi中多线程的简单应用
- SGU101 求有重边的无向图欧拉迹
- 第五周项目1拓展 判断是否为矩形 求矩形面积