【问题标题】:One transaction for several JpaRepositories' methods多个 JpaRepositories 方法的一个事务
【发布时间】:2013-11-26 01:33:19
【问题描述】:

我有一些自动装配接口扩展了 JpaRepository。他们每个人都有针对不同实体的“更新” hql 方法。我从服务的方法中调用这些方法。

如果其中一个失败,我如何让它们在一个事务中执行以回滚所有数据?

service 有 @service 和 @transactional 属性,但没有帮助。

------------ 更新

这里是一个例子。 repository1.updateMethod() 和 repository2.updateMethod() 工作正常,repository3.save 由于约束错误而引发异常。结果,我看到 repository1 和 repository2 方法的结果已保存。我需要它来回滚。

@ Service
@ Transactional(rollbackFor = {RuntimeException.class})
public SomeService {
  @ Autowired SomeRepository repository1;
  @ Autowired AnotherRepository repository2;
  @ Autowired ThirdRepository repository3;
  ...
  @ Transactional(rollbackFor = {RuntimeException.class})
  public void SomeMethod(SomeEntity obj, String someNewValue) {
    try {
      repository1.updateMethod();
      repository2.updateMethod();
      obj.setValue(someNewValue);
      repository3.save(obj);
    } catch (Exception ex) {
      throw new RuntimeException();
    }   
  }
}

【问题讨论】:

  • Exapndong 关于“它不起作用”并发布一些代码可能会有所帮助。在此处查看我之前的评论:stackoverflow.com/questions/19716673/…
  • 在服务方法级别指定 @transactional 应该使该事务下的任何内容都具有事务性,除非您在子事务上将事务类型设置为“需要新”或“不支持”,这将运行那些在他们自己的交易中。您是否通过在 CRUD 中投入一些东西来测试这一点,然后检查事务是否一直回滚?你能分享一些代码吗?
  • @CodeChimp 第一条消息已更新,我添加了示例并扩展了我的意思。
  • 如何获得对服务的引用?向我们展示使用该服务的代码。
  • 一个主题观察:您应该在抛出 RuntimeException 时包含您的异常。您实际上是在狼吞虎咽,只会得到一个空白的RuntimeException。另外,您是否有理由将交易限制为RuntimeException?似乎您想要所有例外...不确定将其包装在 RuntimeExcetion 中会为您买任何东西。

标签: java spring jpa transactions


【解决方案1】:

我想我找到了一种解决方案,但我仍然不明白为什么它不适用于默认用法。

首先,我在 applidationData.xml 中声明了 JpaTransactionManager

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

并在服务中使用它:

@Autowired
JpaTransactionManager jtm;

在我添加代码之前:

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("TxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus ts = jtm.getTransaction(def);

在终点

jtm.commit(ts);

现在,如果某个方法产生异常,它会在最后一行抛出,并且所有更新都会回滚。这就是我所需要的。但是,正如我所说,我仍然不明白为什么它不适用于默认用法。

【讨论】:

  • 您的设置可能有误。我认为@Transactional 在幕后使用了 AOP,所以也许你在那里遗漏了一些关键?此外,如果要回滚异常,则需要将 ts.rollback() 包装在它自己的 try/catch 中。否则,异常将吞噬导致回滚的异常。您最终对原始异常的真正原因视而不见。
猜你喜欢
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
相关资源
最近更新 更多