繁体   English   中英

Spring @Transactional 在服务和非服务方法上的不同行为?

[英]Spring @Transactional different behavior on Service and non-Service methods?

我有一个具有标准架构(控制器 -> 服务 -> 存储库)的 Spring Boot 2.3 REST 应用程序。 出于审计目的,我插入了一个薄层(某种Mediator ),以便我将所有请求持久化到某个特定的服务方法,无论它们是成功持久化还是抛出异常并回滚事务。 例子:

@Component
public class Mediator {

    private final Service service;
    private final AuditService auditService;

    public Mediator(Service service, AuditService auditService) {
        this.service = service;
        this.auditService = auditService;
    }

    @Transactional
    public void saveReport(Report report) {
        try {
            service.saveReport(report);
            auditService.saveReport(report); 
        } catch (Exception exception) {
            auditService.saveReport(report, exception);
            throw exception;
        }
    }
}

于是我遇到了一个奇怪的情况:如果我把@Transactional放在Mediator 的方法上(上面的例子),JPA Repositories 中的所有操作都成功持久化了。 如果我将@Transactional放在 ServiceImpl 方法上(下面的示例)并且不再放在 Mediator 上,则不会运行其中一个删除查询,尽管其余查询执行得很好。 假设我的 ServiceImpl 看起来像:

@Service
public class ServiceImpl implements Service {

    private final RepositoryA repositoryA;
    private final RepositoryB repositoryB;

    public ServiceImpl(RepositoryA repositoryA, RepositoryB repositoryB) {
        this.repositoryA = repositoryA;
        this.repositoryB = repositoryB;
    }

    @Transactional
    public void saveReport(Report report) {
        repositoryA.save(report.getA());
        repositoryB.save(report.getB());
        repositoryB.delete(report.getSomethingElse());
    }
}

关于事务的两种方法之间唯一明显的区别是,在第一个场景中,我对每个 Mediator 调用都有这个:

o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(909894553<open>)] for JPA transaction

在第二种情况下,我有这个:

tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation

我想直接用@Transactional注释 bean 的方法(我在 Mediator 中所做的)和用相同的东西注释 bean 的(即接口注入的实现)方法(我们通常通过注释一个ServiceImpl 方法),但我不确定也无法找出这种奇怪行为的原因。 有谁知道为什么会发生这种情况?

我想这种行为差异是由于 Spring OpenSessionInView 默认启用的。 您必须在 application.yml 中设置

spring:
  jpa:
    open-in-view: false

请参阅OSIV

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM