【问题标题】:Rollback transaction in spring programmatically以编程方式在spring中回滚事务
【发布时间】:2015-06-02 13:36:31
【问题描述】:

我的问题很简单,我想在方法上回滚使用@Transactional 创建的事务,并且仍然能够将一些结果返回给调用者。

@Transactional
public Object myMethod () {
    ...
    // flag transaction for rollback
    return myObject;
}

我看到这个question 似乎建议要么抛出异常(不是我真正想要的)或调用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();,但最终这也会抛出异常(我正在使用JpaTransactionManager)。

知道如何实现我的目标吗?

【问题讨论】:

  • 如何使用 Spring TransactionTemplate 并“手动”处理事务。
  • 也许TransactionAspectSupport.getTransactionManager().rollback(TransactionStatus)?
  • 我们通过抛出一个包装结果的自定义异常解决了一个类似的问题,但我们也不是很喜欢它。使用异常作为常规控制流非常难看。
  • 你是不是在后面改用Hibernate?如果是这样,您可以访问SessionFactory 来获取和回滚当前事务。
  • @Marvin 我正在使用 EclipseLink,但我敢肯定,如果你绕过 TM,它会导致其他问题,所以我不会那样做。

标签: java spring jpa transactions


【解决方案1】:

在更改数据库中的数据之前,我总是对其进行验证。因为在持久化更改时数据必须是有效的,所以我认为抛出异常的正确行为(对于无效数据的情况)。

另一方面,如果您不想在持久化数据之前显式验证数据,请抛出包含您需要的其他字段的覆盖异常。

PS:在我的逻辑中,我认为回滚事务有一个关键原因,除了数据无效。


尝试验证数据并将其保存在数据库中以相同的服务方法在我看来是糟糕的设计。想象一下,如果验证失败,您想返回一个带有验证消息的容器,或者如果事务正确,则返回一个新实体。你的方法应该有什么返回类型?

【讨论】:

  • 我执行了一些更新,然后识别(或不识别)无效情况。我想回滚我所做的更改并返回有意义的信息,所以至少对我来说没有理由抛出异常。为正常的业务流程抛出异常感觉完全是错误的,但并没有说明它非常丑陋且效率低下。
  • 我看到两种可能性:要么你“懒惰”并且抛出异常(由你或由 Spring),或者你验证数据,甚至不尝试持久化数据。据我了解,您可以验证数据(在执行这些更新之前),但您没有,对吗?
  • 验证数据的唯一方法是在数据库上发出选择调用,因为它涉及对数千行的查询,因此不能预先验证。
  • 为什么不只验证一次(而不是再次持久化)?如果您只发出 SELECT 查询(并且不更改任何数据),为什么还要费心回滚事务呢?
  • 我不怕异常,只是在正常情况下使用它们感觉很不对劲。它使我的代码变得丑陋而不自然。然而,目前这是我唯一可行的解​​决方案。我只是想看看 Spring 是否有真正的好方法。
【解决方案2】:

试试

@Transactional(readOnly=true)

离开后会回滚。但请注意:

@Transactional
public void save(){
   trySave();
}
@Transactional(readOnly=true)
private void trySave(){
   ...
}

这将忽略readOnly,因为事务块开始于save()

【讨论】:

  • 小心乐观传播。
  • 不确定我们是否可以根据文档安全地依赖 readOnly 标志。这几乎不是 TM 的提示。
猜你喜欢
  • 1970-01-01
  • 2015-10-08
  • 2018-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
  • 2017-03-06
相关资源
最近更新 更多