SpringBoot 事务传播 REQUIRES_NEW 不会创建新事务
Posted
技术标签:
【中文标题】SpringBoot 事务传播 REQUIRES_NEW 不会创建新事务【英文标题】:SpringBoot Transactional Propagation REQUIRES_NEW doesn't create new Transaction 【发布时间】:2020-10-20 04:36:41 【问题描述】:我有以下场景:
@Service
public class ServiceA
@Autowired private ServiceB serviceB;
public void runA()
serviceB.runB()
@Service
public class ServiceB
@Autowired private ServiceC serviceC;
@Transactional
public void runB()
serviceC.runC()
...rest of the logic
@Service
public class ServiceC
@Autowired private TestRepository testRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean runC()
Optional<TestEntity> testEntityOptional = testRepository.findByKeyAndType("Key", "Type");
if(testEntityOptional.isPresent())
testEntityOptional.get().setActive(true);
return true;
return false;
@Transactional
public interface TestRepository
extends JpaRepository<TestEntity, Integer>, JpaSpecificationExecutor<TestEntity>
@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints(@QueryHint(name = "javax.persistence.lock.timeout", value = "5000"))
Optional<TestEntity> findByKeyAndType(@NotNull String key, @NotNull String type);
我期待下一个流程:
ServiceA.runA()
调用 ServiceB.runB()
ServiceB.runB()
打开 TRANSACTION_1(如果之前打开过,则使用事务),因为默认传播是 REQUIRED
ServiceB.runB()
调用 ServiceC.runC()
ServiceC.runC()
打开 TRANSACTION_2 因为传播是 REQUIRED_NEW
ServiceC.runC()
调用 TestRepository.findByKeyAndType()
按某些条件获取 testEntity
TestRepository.findByKeyAndType()
从数据库返回符合条件的记录并将其锁定以供读取/更新
ServiceB.runC()
处理记录
ServiceB.runC()
返回值并提交 TRANSACTION_2 并释放锁
ServiceB.runB()
返回并提交 TRANSACTION_1
但根据我的测试,情况并非如此。它接缝ServiceC.runC()
不创建新事务(TRANSACTION_2),即使设置了传播REQUIRED_NEW
(或者它在返回时不提交它),并且仅当ServiceB.runB()
返回时才释放锁定(当提交TRANSACTION_1 时)
有人看到我在这里做错了吗?这是 SpringBoot 的正常行为吗?
锁定超时也不起作用: 我正在使用 Postgress v10 for DB,其中 lock_timeout 设置为“0”。
所以看起来@QueryHints(@QueryHint(name = "javax.persistence.lock.timeout", value = "5000"))
不起作用,因为一旦记录被锁定,另一个尝试读取记录的事务会挂起一段时间,直到记录被解锁
【问题讨论】:
感谢您记录财产。我只是调试并 100% 确定没有打开新事务 【参考方案1】:启用logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG
后,我看到的就是这个。包括暂停和恢复。
你的事务经理也是JpaTransactionManager
吗?
2020-06-30 01:11:53.239 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.accessingdatajpa.BlogService.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-06-30 01:11:57.532 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(1968179698<open>)] for JPA transaction
2020-06-30 01:11:57.538 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7f2542f]
2020-06-30 01:12:02.432 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1968179698<open>)] for JPA transaction
2020-06-30 01:12:04.032 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Suspending current transaction, creating new transaction with name [com.example.accessingdatajpa.Service2.save]
2020-06-30 01:12:06.915 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(2143659352<open>)] for JPA transaction
2020-06-30 01:12:06.916 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@42fd8f2f]
2020-06-30 01:12:10.196 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(2143659352<open>)] for JPA transaction
2020-06-30 01:12:11.489 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Participating in existing transaction
2020-06-30 01:12:12.227 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-06-30 01:12:13.082 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(2143659352<open>)]
2020-06-30 01:12:13.109 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(2143659352<open>)] after transaction
2020-06-30 01:12:13.110 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Resuming suspended transaction after completion of inner transaction
2020-06-30 01:12:16.409 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-06-30 01:12:17.541 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1968179698<open>)]
2020-06-30 01:12:17.542 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(1968179698<open>)] after transaction
【讨论】:
以上是关于SpringBoot 事务传播 REQUIRES_NEW 不会创建新事务的主要内容,如果未能解决你的问题,请参考以下文章
spring中事务传播解读:PROPAGATION_REQUIRES_NEW
Spring事务传播行为REQUIRES_NEW和NESTED用法栗子
Spring事务传播行为REQUIRES_NEW和NESTED用法栗子
spring事务传播行为之使用REQUIRES_NEW不回滚
为啥即使在 Spring 服务类的第二个方法中传播 = Propagation.REQUIRES_NEW 时事务也会回滚?