Spring Boot中@Transactional的Mandatory事务传播行为是否不符合预期?
Spring Boot中@Transactional的Mandatory事务传播行为是否不符合预期?
你好!咱们一步步拆解你的疑问,先把关键理清楚:
先明确Mandatory传播行为的核心规则
你说的完全没错,Propagation.MANDATORY的定义就是必须在已存在的事务中执行,如果当前没有事务就直接抛出异常。从你的日志能看出来,method2没有报错,说明它确实成功加入了method1开启的事务,这一点是符合预期的。
为什么日志里的事务名不一样?
你疑惑的核心点在于日志中method2的事务名是自己的全限定名,而非method1的。这里要区分两个容易混淆的概念:Spring事务切面记录的事务名称和底层数据库事务实例。
- 当你调用
TransactionAspectSupport.currentTransactionStatus().transactionName时,获取的是Spring事务切面在处理当前@Transactional方法时设置的名称,默认值就是当前方法的全限定名。 - 不管传播行为是MANDATORY、REQUIRED还是SUPPORTS,只要Spring事务切面处理这个方法,就会把当前事务状态中的
transactionName更新为当前方法的名称,但底层的数据库事务实例还是同一个(也就是method1用REQUIRES_NEW开启的那个)。
你可以做个小验证:在两个方法里都打印事务实例的哈希值,比如:
log.error("Transaction instance hash: " + TransactionAspectSupport.currentTransactionStatus().transaction.hashCode())
会发现method1和method2打印的哈希值完全相同,这就实锤了它们用的是同一个数据库事务。
这不是bug,是Spring的设计逻辑
Spring把事务名设置为当前方法的名称,主要是为了日志和监控方便,让你能快速定位到当前是哪个方法在操作事务。但从实际事务的执行逻辑来看,method2确实是在method1开启的事务中运行的,完全符合MANDATORY的传播规则。
所以你的判断有误哦,这不是Spring的bug,只是事务名称的显示逻辑和你预期的不一样而已。
备注:内容来源于stack exchange,提问作者Roman Q
相关产品推荐
相关产品推荐

