Altough事务管理工作Spring Data Repositories创建自己的事务并暂停活动事务。
我有以下Spring应用程序:
申请类:
@SpringBootApplication
@EnableTransactionManagement
public class SpringbootTxApplication {... }
服务类:
@Service
public class EntityService {
...
public void addEntityWithoutTransaction(MyEntity myEntity) {
log.debug("addEntityWithoutTransaction start");
myEntityRepository.save(myEntity);
log.debug("addEntityWithoutTransaction end");
}
@Transactional
public void addEntityTransaction(MyEntity myEntity) {
log.debug("addEntityTransaction start");
myEntityRepository.save(myEntity);
log.debug("addEntityTransaction end");
}
}
在执行我的EntityServiceTest时执行每个方法一次并在跟踪中使用spring事务日志,我得到以下输出:
... TRACE ... o.s.t.i.TransactionInterceptor : Getting transaction for [de.miwoe.service.EntityService.addEntityTransaction]
... DEBUG ... de.miwoe.service.EntityService : addEntityTransaction start
... TRACE ... o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
... TRACE ... o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
... DEBUG ... de.miwoe.service.EntityService : addEntityTransaction end
... TRACE ... o.s.t.i.TransactionInterceptor : Completing transaction for [de.miwoe.service.EntityService.addEntityTransaction]
和
... DEBUG ... de.miwoe.service.EntityService : addEntityWithoutTransaction start
... TRACE ... o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
... TRACE ... o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
... DEBUG ... de.miwoe.service.EntityService : addEntityWithoutTransaction end
显然根据日志,@ Transactional-Annotation正在addEntityTransaction中工作,但存储库仍然创建自己的事务。
为什么呢?官方文档(https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions)描述如果它已经存在,它不应该开始新的。
(有时,“约定优于配置”似乎更像是对约定优于配置的激怒......)
我错过了什么吗?
(完整代码也可在此处获取:https://github.com/miwoe/springboot-tx)
答案 0 :(得分:7)
您的问题(要点):
... TRACE ... o.s.t.i.TransactionInterceptor : Getting transaction for [de.miwoe.service.EntityService.addEntityTransaction]
... DEBUG ... de.miwoe.service.EntityService : addEntityTransaction start
... TRACE ... o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
... TRACE ... o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
... DEBUG ... de.miwoe.service.EntityService : addEntityTransaction end
... TRACE ... o.s.t.i.TransactionInterceptor : Completing transaction for [de.miwoe.service.EntityService.addEntityTransaction]
显然根据日志,@ Transactional-Annotation是 在addEntityTransaction中工作,但存储库仍然创建它 自己的交易。
答案: 您在一个物理交易中工作。
当启动呼叫服务弹簧启动新事务并设置TransactionStatus.isNewTransaction = true
时,当您
call dao方法spring检查那个方法也是事务性的,并为dao创建第二个事务,BUT设置为第二个事务TransactionStatus.isNewTransaction = false
。如果你为dao方法/类设置required_new只在这种情况下它被标记为TransactionStatus.isNewTransaction = true.
在提交时,仅提交第一个事务(物理)。如果您标记第二个事务,它将在提交时被忽略,并且第一个事务将被提交。
AbstractPlatformTransactionManager
if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
doCommit(status);
}
您可以检查调试模式。
要点:您在一个可能被标记为提交或回滚的事务中工作。在TRACE中,您会看到有关Spring事务执行的详细信息,并且对于您而言,在物理上创建了多少逻辑事务无关紧要交易。对于传播级别为REQUIRED的事务,您有保证,如果从另一个事务方法调用事务方法,则只创建一个物理事务,并且提交或回滚一个事务。
当传播设置为PROPAGATION_REQUIRED时,为逻辑 为设置所在的每个方法创建事务范围 应用。每个这样的逻辑事务范围都可以确定 仅具有回滚状态,具有外部事务范围 在逻辑上独立于内部事务范围。的 当然,在标准的PROPAGATION_REQUIRED行为的情况下,所有这些 范围将映射到同一物理事务。那么一个 内部事务范围中设置的仅回滚标记确实会影响 外部交易实际提交的机会(正如您所期望的那样) 它来)。
答案 1 :(得分:5)
存储库方法是@Tranactional
,因为您正在利用JpaRepository
接口并允许框架为您实现。
默认选择SimpleJpaRepository,使用@Transactional
。看看来源,你会看到它的使用位置。