Spring数据事务跨越多个存储库

时间:2017-07-21 09:33:03

标签: java spring hibernate spring-data

我需要使用相同的事务将2个不同的实体插入2个不同的表中。如果第二个插入失败,则应回滚第一个插入。

有没有办法很好地做到这一点?

伪代码:

start tx
repo1.save(myEntity);
repo2.save(anotherEntity);
try commit

我知道您可以利用@Transactioal,但仅限于方法级别?

3 个答案:

答案 0 :(得分:2)

1)您需要检查您是否设置了autocommit = false。

2)将保存操作包装到一个服务方法中并使其成为@Transactioal。但是,如果使用save()自定义方法检查,保存未标记为@Transactioal,传播级别为required_new或嵌套。如果需要,可以使用REQUIRES_NEW保存服务方法,使此服务方法事务独立于其他事务。

你也可以用TransactionTemplate包装。

@Autowired
private TransactionTemplate transactionTemplate;

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    @Override
    public void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
            repo1.save(myEntity);
            repo2.save(anotherEntity);
    });

答案 1 :(得分:0)

在存储库方法周围声明@Transactional通常是错误的想法。

存储库仅供您访问域实体。业务逻辑通常涉及多个域实体以及它们之间的协作。

在您的架构中,您应该有一个层来构建业务逻辑。这通常对应于暴露于外部的服务。

这通常是您应该设置交易边界的地方。通常它是一个Controller或一个Service方法。

答案 2 :(得分:-1)

要遵循的步骤:

  1. 确保对repo1和repo2方法使用接口,因为spring事务在代理上工作。 (如果您只使用类,那么您可能需要添加一些其他依赖项。)
  2. 使用@Transactional(propagation = Propagation.REQUIRED)注释批注repo1.save(..)和repo2.save(..)。
  3. 从课堂外的任何方法调用repo1.save()。
  4. 使用special junit runner正确地对代码进行单元测试。
相关问题