You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

控制器层存在父事务时,JpaRepository上的@Transactional(REQUIRES_NEW)注解未生效原因排查

Why Doesn't @Transactional(REQUIRES_NEW) Work on My Spring Data JPA Repository Interface?

Let’s break down exactly why your Repository-level transaction configuration isn’t behaving as expected, while the Service-level one works perfectly:

The Root Cause: @Transactional Doesn’t Inherit to Inherited Methods

The core issue boils down to Java’s annotation rules: the @Transactional annotation does not have the @Inherited meta-annotation. This means when you add @Transactional(REQUIRES_NEW) to your EventRepo interface, it won’t automatically apply to methods inherited from JpaRepository (like the save() method you’re calling).

Here’s the step-by-step breakdown:

  1. Spring Data JPA’s default transaction behavior: CRUD methods like save() from CrudRepository/JpaRepository come with a default @Transactional(propagation = Propagation.REQUIRED) annotation. This means they’ll join an existing transaction if one is already active.
  2. Your Repository interface annotation doesn’t override defaults: Since @Transactional isn’t inherited, adding it to EventRepo doesn’t change the behavior of the inherited save() method. The method still uses the default REQUIRED propagation.
  3. What happens in your controller flow:
    • The controller’s processRequest() runs in a REQUIRES_NEW transaction.
    • You call service.save(event)—but since your ApplicationService has no transactional annotations, this is a plain method call (no AOP proxy wraps it).
    • When eventRepo.save(event) executes, it uses the default REQUIRED propagation, so it joins the controller’s existing transaction.
    • If the controller throws a RuntimeException, the entire controller transaction rolls back—including the save() operation.

Why the Service-Level Annotation Works

When you add @Transactional(REQUIRES_NEW) to your IApplicationService interface:

  • The save() method is declared directly in this interface, so the @Transactional annotation applies directly to it (no inheritance is involved here).
  • Spring creates an AOP proxy for your ApplicationService bean. When the controller calls service.save(event), it goes through this proxy, which starts a new, independent transaction.
  • Even if the controller’s transaction rolls back later, the Service’s transaction has already committed the save() operation, so the record remains in the database.

How to Fix the Repository-Level Scenario

If you want to make REQUIRES_NEW work on the Repository layer, you need to explicitly override the save() method and apply the annotation directly to it:

public interface EventRepo extends JpaRepository<Event, Integer> {
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
    <S extends Event> S save(S entity);
}

By doing this, the @Transactional(REQUIRES_NEW) annotation is directly tied to the save() method, and Spring Data JPA will use this configuration instead of the default.

内容的提问来源于stack exchange,提问作者Pavan Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:32:34