春季数据:JPA和嵌套事务

时间:2019-02-18 15:35:11

标签: java spring jpa kotlin spring-data-jpa

我在使用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方法和sendEmail方法上引发的异常甚至不会执行。

因为方法UserService.saveUser的传播设置为Propagation.REQUIRES_NEW,所以我希望提交事务(执行SQL语句),并传播任何异常。

我没有设置与“交易”相关的任何内容,因此我认为刷新模式设置为“自动”。

有人可以发现我在做什么错或我的误解吗?

1 个答案:

答案 0 :(得分:2)

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

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

最简单的解决方案是将方法移至另一个@Service或bean。如果您真的想将其保留在同一组件中,则需要调用它,以便在Spring AOP中将其包装在代理中。您可以这样做:

private YourClass self;

@Autowired
private ApplicationContext applicationContext;

@PostConstruct
public void postContruct(){
    self = applicationContext.getBean(YourClass.class);
}

然后在self上调用方法将导致打开交易。

换句话说:您没有遇到任何异常,因为@Transactional超过saveUser无效。