当存在以下调用链时:rest方法 -> service1的事务方法(
propagation=Requires_New
) -> service2的事务方法(propagation=Mandatory
):
@Service
class Service1(
private val service2: Service2
) {
private val log = LoggerFactory.getLogger(this.javaClass)
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun method1() {
log.error("Transaction for method1: " + TransactionAspectSupport.currentTransactionStatus().transactionName)
service2.method2()
}
}
@Service
class Service2 {
private val log = LoggerFactory.getLogger(this.javaClass)
@Transactional(propagation = Propagation.MANDATORY)
fun method2() {
log.error("Transaction for method2: " + TransactionAspectSupport.currentTransactionStatus().transactionName)
}
}
日志打印以下内容(日志应该打印每个方法的当前事务的名称):
sb-repro | 2024-02-20T13:20:25.000Z ERROR 1 --- [sb-repro] [ scheduling-1] c.r.s.persistence.service.Service1 : Transaction for method1: com.romankudryashov.sbrepro.persistence.service.Service1.method1
sb-repro | 2024-02-20T13:20:25.000Z ERROR 1 --- [sb-repro] [ scheduling-1] c.r.s.persistence.service.Service2 : Transaction for method2: com.romankudryashov.sbrepro.persistence.service.Service2.method2
我认为这是错误的(考虑到
Mandatory
传播应该是Support a current transaction, throw an exception if none exists
)并且method2
的数据库事务应该是com.romankudryashov.sbrepro.persistence.service.Service1.method1
。
我错了还是这是一个错误?
复制器在这里:https://github.com/rkudryashov/sb-repro。您只需拨打电话
http://localhost:8080/test
(无需构建原生镜像即可重现。)
我认为这是因为
TransactionAspectSupport.currentTransactionStatus().transactionName
对于嵌套方法调用的行为不一致
我稍微改变了代码:
@Service
class Service1(
private val service2: Service2
) {
private val log = LoggerFactory.getLogger(this.javaClass)
@Transactional(propagation = Propagation.REQUIRES_NEW)
fun method1() {
log.error("Name from TransactionAspectSupport: " + TransactionAspectSupport.currentTransactionStatus().transactionName)
log.error("Name from TransactionSynchronizationManager: " + TransactionSynchronizationManager.getCurrentTransactionName())
service2.method2()
}
}
@Service
class Service2 {
private val log = LoggerFactory.getLogger(this.javaClass)
@Transactional
fun method2() {
log.error("Name from TransactionAspectSupport: " + TransactionAspectSupport.currentTransactionStatus().transactionName)
log.error("Name from TransactionSynchronizationManager: " + TransactionSynchronizationManager.getCurrentTransactionName())
}
}
现在打印:
2024-02-22T12:16:27.239+03:00 ERROR 14928 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service1 : Name from TransactionAspectSupport: com.romankudryashov.sbrepro.persistence.service.Service1.method1
2024-02-22T12:16:27.239+03:00 ERROR 14928 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service1 : Name from TransactionSynchronizationManager: com.romankudryashov.sbrepro.persistence.service.Service1.method1
2024-02-22T12:16:27.239+03:00 ERROR 14928 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service2 : Name from TransactionAspectSupport: com.romankudryashov.sbrepro.persistence.service.Service2.method2
2024-02-22T12:16:27.239+03:00 ERROR 14928 --- [sb-repro] [nio-8080-exec-1] c.r.s.persistence.service.Service2 : Name from TransactionSynchronizationManager: com.romankudryashov.sbrepro.persistence.service.Service1.method1
也就是说
TransactionAspectSupport
和 TransactionSynchronizationManager
行为不同
如果我删除上面的
@Transactional
,一切都是正确的:method2