Java中RollbackException的处理

发布于 2024-08-09 17:44:12 字数 144 浏览 1 评论 0原文

有什么办法可以“重放”交易吗? 我的意思是,有时我会收到 RollbackException 并回滚事务。然后我可以“克隆”事务并重试,或者一旦调用回滚,事务就会丢失吗? 我真的需要这些更改,并且真的不想跟踪每个更改以便稍后重新运行...

谢谢, 乌迪

Is there any way to "replay" transaction?
I mean, sometimes I get RollbackException and rollback the transaction. Can I then "clone" the transaction and try again, or once rollback is called, transaction is lost?
I really need the changes, and really don't want to trace every change for rerunning later...

thanks,
udi

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

网名女生简单气质 2024-08-16 17:44:12

为什么你首先会遇到异常?在我看来,这就是问题的关键。

你依赖乐观的写作吗?如果是这样,那么您将必须以某种形式的循环包装数据库写入,并结合(可能)回退和多次重试。不幸的是,您无法自动执行此操作(除非您研究某种形式的包装数据库的 AOP 解决方案使用重试策略写入?)

Why do you get the exception in the first place ? This seems to me to be the crux of the matter.

Are you relying on optimistic writing ? If so, then you'll have to wrap your database writes in some form of loop, incorporating (perhaps) a backoff and a number of retries. You can't do this automatically, unfortunately (unless you investigate some form of AOP solution wrapping your database writes with a retry strategy ?)

方觉久 2024-08-16 17:44:12

这取决于交易来自哪里。在 Java/JDBC 中,事务与连接相关联。您可以通过将 setAutoCommit() 设置为 false 来启动一个事务(否则,每个语句都会变成自己的小事务)。

没有什么可以阻止您在事务失败后重用连接(即您调用回滚)。

当您使用 Spring 时,事情会变得更加棘手。 Spring 将您的方法包装在事务处理程序中,并且该处理程序尝试根据方法中抛出的异常来猜测它应该对当前事务执行什么操作。下一个问题是:哪个包装器创建了当前事务?我刚刚遇到一个情况,我会调用一个方法 foo() ,该方法又会调用 bar() ,两者都是 @Transactional

我想捕获 foo()bar() 的错误并将它们保存到数据库中。这不起作用,因为事务是为 foo() 创建的(所以我仍然处于 Spring 认为被 bar() 中的异常破坏的事务中)并且它不让我保存错误。

解决方案是创建 baz(),使其成为 @Transactional(propagation=Propagation.REQUIRES_NEW) 并从 foo() 调用它。 baz() 将获得一个新的、全新的事务,并且能够写入数据库,即使它是从已经有一个(损坏的)事务的 foo() 调用的。

That depends where that transaction comes from. In Java/JDBC, a transaction is tied to a connection. You start one by setting setAutoCommit() to false (otherwise, every statement becomes its own little transaction).

There is nothing preventing you from reusing the connection after a transaction failed (i.e. you called rollback).

Things get more tricky when you use Spring. Spring wraps your methods in a transaction handler and this handler tries to guess what it should do with the current transaction from the exceptions that get thrown in the method. The next question is: Which wrapper created the current transaction? I just had a case where I would call a method foo() which would in turn call bar(), both @Transactional.

I wanted to catch errors from bar() in foo() and save them into the DB. That didn't work because the transaction was created for foo() (so I was still in a transaction which Spring thought broken by the exception in bar()) and it wouldn't let me save the error.

The solution was to create baz(), make it @Transactional(propagation=Propagation.REQUIRES_NEW) and call it from foo(). baz() would get a new, fresh transaction and would be able to write to the DB even though it was called from foo() which already had a (broken) transaction.

余生再见 2024-08-16 17:44:12

另一种选择是使用 JDBC 保存点 部分滚动后退。

Another alternative is to use JDBC savepoints to partly roll back.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文