Spring Boot和Spring数据jpa中的事务管理

时间:2017-07-18 20:17:44

标签: spring-boot spring-data-jpa

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

2 个答案:

答案 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时,为逻辑   为设置所在的每个方法创建事务范围   应用。每个这样的逻辑事务范围都可以确定   仅具有回滚状态,具有外部事务范围   在逻辑上独立于内部事务范围。的   当然,在标准的PROPAGATION_REQUIRED行为的情况下,所有这些   范围将映射到同一物理事务。那么一个   内部事务范围中设置的仅回滚标记确实会影响   外部交易实际提交的机会(正如您所期望的那样)   它来)。

答案 1 :(得分:5)

存储库方法是@Tranactional,因为您正在利用JpaRepository接口并允许框架为您实现。

默认选择SimpleJpaRepository,使用@Transactional。看看来源,你会看到它的使用位置。