Java Spring数据:JPA和嵌套事务

Java Spring数据:JPA和嵌套事务,java,spring,jpa,kotlin,spring-data-jpa,Java,Spring,Jpa,Kotlin,Spring Data Jpa,我对Spring JPA数据和嵌套事务有问题。下面是我的服务的嵌套事务的两个方法 @Service public UserService { @Transactional public User createUser(UserDto userDto) { .... user = saveUser(user); sendEmail(user); .... } @Transactional(propa

我对Spring JPA数据和嵌套事务有问题。下面是我的服务的嵌套事务的两个方法

@Service
public UserService {

    @Transactional
    public User createUser(UserDto userDto) {
        ....
        user = saveUser(user);
        sendEmail(user);
        ....
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public User saveUser(User user) {
        return userRepository.save(user);
    }
有一种情况是,userRepository.save()方法应该引发异常,但不知何故没有引发异常,看起来它正在等待父事务完成。我期望saveUser方法和sendmail方法上抛出的异常不会被执行

因为方法
UserService.saveUser
将传播设置为
propagation.REQUIRES\u NEW
,所以我希望提交该事务(要执行的SQL语句)并传播任何异常

我没有设置任何与事务相关的内容,因此我相信刷新模式设置为自动


有人能看出我做错了什么或我的误解是什么吗?

这是因为您正在同一个bean中调用
@Transactional
方法

@Transactional
仅适用于在spring创建的代理上调用的方法。这意味着,当您创建@Service或其他bean时,从外部调用的方法将是事务性的。如果从bean内部调用,则不会发生任何事情,因为它不会通过代理对象

最简单的解决方案是将该方法移动到另一个@Service或bean。若您真的想将它保存在同一个组件中,那个么您需要调用它,以便SpringAOP将它包装在代理中。您可以这样做:

private YourClass self;

@Autowired
private ApplicationContext applicationContext;

@PostConstruct
public void postContruct(){
    self = applicationContext.getBean(YourClass.class);
}
然后在
self
上调用方法将导致打开一个事务


换句话说:您没有遇到任何异常,因为
@Transactional
over
saveUser
不起作用。

这是因为您正在从同一个bean中调用
@Transactional
方法

@Transactional
仅适用于在spring创建的代理上调用的方法。这意味着,当您创建@Service或其他bean时,从外部调用的方法将是事务性的。如果从bean内部调用,则不会发生任何事情,因为它不会通过代理对象

最简单的解决方案是将该方法移动到另一个@Service或bean。若您真的想将它保存在同一个组件中,那个么您需要调用它,以便SpringAOP将它包装在代理中。您可以这样做:

private YourClass self;

@Autowired
private ApplicationContext applicationContext;

@PostConstruct
public void postContruct(){
    self = applicationContext.getBean(YourClass.class);
}
然后在
self
上调用方法将导致打开一个事务


换句话说:您没有遇到任何异常,因为
@Transactional
over
saveUser
不起作用。

为什么您认为userRepository.save()应该引发异常?如果它被抛出,saveUser事务将被回滚。所以我期待着一个异常会立即抛出,甚至不会调用sendEmail。然而,只有在createUser完成时才会引发saveUser异常。下面的方法解决了这个问题。非常感谢Simon为什么您认为userRepository.save()应该抛出和异常?如果它被抛出,saveUser事务将被回滚。所以我期待着一个异常会立即抛出,甚至不会调用sendEmail。然而,只有在createUser完成时才会引发saveUser异常。下面的方法解决了这个问题。非常感谢西蒙谢谢你。你的建议很管用。没问题,很乐意帮忙:)非常感谢。你的建议非常有效。没问题,很乐意帮忙:)