Spring/Hibernate事务持久化上下文共享:接口更新行为不符预期咨询
问题原因分析
1. post1方法(无@Transactional注解)
- 调用
entityManager.find()时,因为没有事务边界,Spring会创建一个绑定到当前线程的EntityManager实例,查询得到的FileEntity处于托管状态(被持久化上下文跟踪)。 - 修改实体的
description后,持久化上下文会标记该实体为脏数据。 - 调用
barService.bar()时,REQUIRES_NEW会开启一个独立的新事务,执行完毕后提交,但这个新事务和之前的持久化上下文无关联。 - 请求结束时,Spring会清理线程绑定的EntityManager,此时Hibernate会自动flush持久化上下文中的脏数据到数据库——非事务环境下EntityManager默认flush模式为
AUTO,关闭前会触发flush操作。
2. post2方法(@Transactional(TxType.SUPPORTS)注解)
SUPPORTS的规则是:存在外部事务则加入,否则以非事务方式执行。这里没有外部事务,所以方法以非事务方式运行,但Spring会创建一个空的事务上下文。- 调用
entityManager.find()获取并修改实体后,持久化上下文同样标记脏数据,但此时EntityManager的flush模式被事务上下文设置为COMMIT——仅在事务提交时才会触发flush。 - 调用
barService.bar()开启的新事务提交后,不会影响原持久化上下文。 - 方法结束时,由于没有实际的事务提交动作,Spring关闭EntityManager时不会触发flush,脏数据不会同步到数据库。
核心差异
- 无
@Transactional的方法中,EntityManager处于无事务上下文环境,关闭时自动flush脏数据; - 标记
SUPPORTS的方法中,即使无实际事务,Spring的事务上下文会强制EntityManager仅在事务提交时flush,而方法结束时没有提交动作,因此不会触发数据库更新。
内容的提问来源于stack exchange,提问作者Sed Mehdi
相关产品推荐
相关产品推荐

