clear和flush使用不当导致数据更改操作在事务提交前已从缓存中清除

1.问题背景

entity层:

在实体中创建了自己的一对多的关联属性,即一方是自己本身,而多方是关联的集合属性,集合中的每个对象也是自己本身。

 

Service层:

产生的需求:修改了一个对象的unitPath属性,那么所有从属于这个对象的1-n层下级对象也都需要修改自身的unitPath属性,这便涉及到了递归的问题。

 

递归更改属性:

 

然而,在运行程序的过程中发现,递归方法的执行并没有产生应有的效果,实际效果是递归更改对象的1-n层下级对象中,永远只有第n级具有更改的效果,不论n是几。也就是说,只有递归的最后一层对象执行了。

 

如上效果,将三层嵌套的v对象更改路径,v原来在c目录下,后更改到z目录下,只有第三层关联对象实现了相应的更改。同理,四层嵌套的z对象也是如此。

 

2.问题解析

在针对程序的最初设计中,在更改对象属性的merge操作中,数据就应该保存到数据库中。但从效果上看来,merge之后并没有真正将更改后的数据刷新到数据库中去,姑且先查看下程序发出的sql语句。结果显示,每次程序都只发出一条update语句,这便是问题所在,因此又查看了merge方法的实现。

 

在底层的方法实现中,在执行sessionmerge方法之前,先执行了一步sessionclear方法。那么,clear方法为什么影响了我们程序的执行呢?

 

3.问题解决

首先来研究下merge方法。merge的作用是如果没有该条记录,则会被创建,如果有该条记录,但内容有变,则会被修改。merge后,对象的状态仍然为托管状态。并且,对对象修改的sql也要等到事务完全提交才会执行。

其次session是有一级缓存的,目的是为了减少查询数据库的时间,提高效率,一级缓存的生命周期和session是一样的,session.flush()session.clear()就针对session的一级缓存的处理。简单的说,1 session.flush()的作用就是将session的缓存中的数据与数据库同步。2 session.clear()的作用就是清除session中的缓存数据(不管缓存与数据库的同步)。

综上所述,如果使用了clear,那么在事务结束的时候,这条数据是不会被持久化到数据库中的,因为一般缓存是在事务提交的时候进行清理的,当在清理缓存前就把缓存给清除了,自然就不会同步到数据库了。所以需要在merge语句之后再执行一下sessionflush()方法,手动将缓存中的数据同步到数据库就可以了。

 

 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值