@Transactional 对 JpaRepository 没有影响

@Transactional has no effect on JpaRepository

我在控制器层有一个父事务,但我想在调用存储库时启动一个新事务,为了实现这一点,我尝试如下注释存储库接口

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

然而,这似乎不会在调用 EventRepo#save 时启动新事务。为什么?

这是我的服务层。

public interface IApplicationService {
   void save(Event event);
}

@Service
public class ApplicationService implements IApplicationService {
@Autowired
private EventRepo eventRepo;

@Override
public void save(Event event) {
    eventRepo.save(event);
}
}

从controller层依次调用

@RequestMapping(value="/{indicator}", method=RequestMethod.POST)
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
@ResponseBody
public String processRequest(@PathVariable Integer indicator) {
    
    Event event = new Event("Student1");
    service.save(event);
    
    if(indicator != 0) {
        throw new RuntimeException();
    }
    
    return "Success";
}

然而,如果我用 @Transactional 注释服务接口,一切都会完美无缺

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
public interface IApplicationService {
   void save(Event event);
}

当我说工作的意思是,如果我 运行 下面的 curl 命令,我将在 h2 db 中看到事件实体的 2 行

   curl -X POST http://localhost:8080/1
   curl -X POST http://localhost:8080/0

我理解最好在服务层控制事务,然后在存储库或控制器层控制事务,以这种方式构建情况可以很容易地演示问题。

Spring开机启动版本为2.5.6 下面的依赖项具有由 springboot starter

管理的版本

这里有一个帖子建议注释 Repository 层应该没问题,尽管不鼓励这样做。 @Transactional on a JpaRepository

this Spring article中我们可以读到以下内容:

Additionally, we can get rid of the @Transactional annotation for the method as the CRUD methods of the Spring Data JPA repository implementation are already annotated with @Transactional.

对我来说,这意味着您添加到 EventRepo 的任何 @Transactional 注释都将被上面提到的 CRUD 方法中的 @Transactional 注释覆盖。话虽如此,我真的怀疑 @Transactional 注释对 JpaRepository 方法有任何影响。它在您自己的自定义方法中会有,但在我看来它在继承的方法中有 none。

为了在 EventRepo#save 中应用您自己的事务设置,覆盖保存方法:

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

说明

Spring 忽略您的 @Transactional 注释,因为它无法在 EventRepo 代理中找到 save 方法,并应用来自父 CrudRepository 的默认事务设置]界面。

进一步阅读How Does Spring @Transactional Really Work?