簡體   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