Hibernate持久化对象与事务的坑

今天排查项目Bug时发现了一个问题,有一个数据库的记录被莫名其妙更新了,查看了相关的业务代码,并没有发现有任何的save保存方法被调用

java 复制代码
ActionEntity byActionId= actionEntityRepository.findAllByActionId(actionId);
byActionId.setActionNumberScript(NumberUtils.toInt(personalizationSolutionsEntity.getActionNumber());
byActionId.setActionGroupScript(NumberUtils.toInt(personalizationSolutionsEntity.getActionGroupNumber());
byActionId.setActionDuration(personalizationSolutionsEntity.getActionDuration());

如以上(简洁)代码所示,仅仅是查出了这个对象,set了一些属性,并没有调用save方法进行更新,但是最后结果还是数据库被更新了,经过排查后,确定是Hibernate机制的问题,如果修改了经过Hibernate框架查出的对象,并且加了非只读事务管理,那么Hibernate会在事务提交的时候自动更新数据到数据库无论你是否调用save方法

先说解决办法

  1. 去掉事务(大多数情况下不太可行)

  2. 对不需要同步数据库的对象,查出后直接new一个新对象,复制属性替代原对象进行操作即可

Hibernate 对象状态

凡是经过 Hibernate 框架查出的对象,统一是持久化状态,持久化状态的对象会被关联存储在Hibernate SqlSession 的缓存中,在之后对这个对象任何的修改都会被记录到缓存里去,当然正常情况下你不调用 save 方法,这些缓存并不会同步到数据库中去,但是重点来了,如果你在方法上添加了@transactional 注解,那么Hibernate会自动在事务提交的时候将缓存中的数据同步到数据库中。

解决办法的第二种new一个新对象,这个对象的状态就是脱管,不归属于Hibernate管理,所以不会出现缓存自动同步问题

Hibernate 缓存与事务关系

如果你指定的事务是只读事务,

java 复制代码
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)

那么Hibernate并不会对数据库进行修改,因为这个注解告诉它只需要读取,无需写入

但是如果你使用了多层事务,也就是说最外层是只读事务,但是内层嵌套了普通事务,那么Hibernate还是会对缓存中的数据进行同步到数据库操作。

相关推荐
孔明兴汉2 分钟前
Cursor MCP 第一章-第一节-MCP协议简介.md
java·ai
信仰_2739932432 分钟前
枚举类Enum反编译后效果
java·开发语言
TDengine (老段)12 分钟前
TDengine 数学函数 LOG 用户手册
java·大数据·数据库·时序数据库·iot·tdengine·涛思数据
青皮桔17 分钟前
Java+OpenCV实现图片切割
java·后端·opencv·计算机视觉
兮动人22 分钟前
Spring中@Configuration注解的proxyBeanMethods属性详解
java·后端·spring
zl97989923 分钟前
SpringBoot-数据访问之Druid
java·spring boot
猫头虎1 小时前
解决升级IDEA2025.2后,每次打开Maven项目爆红的问题:Windows和Mac解决方案
java·ide·macos·maven·intellij-idea·idea·intellij idea
NFG89C1 小时前
Adobe Lightroom Classic 2025解锁版 (专业照片管理)
java·adobe·工具
蒙奇D索大1 小时前
【计算机网络】408计算机网络高分指南:物理层编码与调制技术精讲
java·前端·学习·计算机网络
豐儀麟阁贵1 小时前
5.2 类
java·开发语言