Null @Version 列的 org.springframework.transaction.UnexpectedRollbackException
我在我的应用程序中使用 Spring 3.0.4-RELEASE、JPA 2.0 和 Hibernate 作为提供程序,并使用 JTA JOTM 进行事务处理。在对实体对象调用 entityManager.merge
时,我收到以下错误:
org.objectweb.jotm.SubCoordinator commit_one_phase
INFO: Rollback during beforeCompletion in SubCoordinator.commit_one_phase
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException
at
org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1012)
此错误是由于通过 Talend ETL 作业将数据直接插入数据库 (MySQL) 造成的。我注意到数据库中的 @Version
列有 NULL
值,并决定将它们设置为 0,这解决了问题。
为什么@Version
列不能为NULL
?还有其他人遇到过这个问题吗?谢谢。
I'm using Spring 3.0.4-RELEASE, JPA 2.0 with Hibernate as a provider, and JTA JOTM for transactions in my application. I've received the following error when calling entityManager.merge
on my entity object:
org.objectweb.jotm.SubCoordinator commit_one_phase
INFO: Rollback during beforeCompletion in SubCoordinator.commit_one_phase
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException
at
org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1012)
This error came as a result of inserting data directly into the database (MySQL) through our Talend ETL job. I noticed that my @Version
column in the database had NULL
values and decided to set them to 0 and this resolved the issue.
Why can't the @Version
column be NULL
? Has anyone else come across this issue? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您想完全了解这里发生的情况,请激活日志记录以准确查看导致
RollbackException
的原因(我怀疑“坏“SQL)。请注意,您没有收到
OptimisticLockException
,我认为 Hibernate 在某种程度上对NULL
版本感到困惑。我并没有真正挖掘这个问题,也无法详细解释它,但似乎 Hibernate 甚至没有生成预期的合并UPDATE
语句。正如我所写,我无法给出确切的原因,但我很想回答:因为这不是 Hibernate 所期望的值。 Hibernate 将以
0
作为版本列的初始值,我的建议是尊重 Hibernate 的期望并将其设置为默认值。如果您想了解为什么将
NULL
设置为初始值会导致问题,您必须调试 Hibernate 的代码。但老实说,这听起来像是浪费时间:因为您使用的是 Hibernate,所以在绕过 Hibernate API 时只需尊重/模仿 Hibernate 的行为即可。If you want to fully understand what is happening here, activate logging to see exactly what is resulting in the
RollbackException
(I suspect "bad" SQL).Note that you aren't getting an
OptimisticLockException
, I think that Hibernate is somehow getting confused by theNULL
version. I didn't really dig the problem and can't explain it in details but it seems Hibernate isn't even generating the expectedUPDATE
statement for the merge.As I wrote, I can't give the exact reason but I'm tempted to answer: because that's not a value expected by Hibernate. Hibernate would start with
0
as initial value for the version column, my suggestion would be to respect Hibernate's expectation and set that as default value.If you want to understand why setting
NULL
as initial value is causing troubles, you'll have to debug Hibernate's code. But honestly, this sounds like a waste of time: since you're using Hibernate, simply respect/mimic Hibernate's behavior when bypassing Hibernate's API.您期望什么行为?
当您对分离对象执行合并时,如果分离实体的版本与数据库中的版本不匹配,则会引发开放式并发异常。我猜在你的情况下,这个异常被包装到
UnexpectedRollbackException
中。如果分离实体的版本为0
,则将数据库中的版本列设置为0
可以解决此问题。真正的解决方案是当外部软件更改时增加数据库中实体的版本。这与乐观锁定策略是一致的。
What behaviour do you expect?
When you perform
merge
on detached object, optimistic concurrency exception is thrown if version of the detached entity doesn't match version in the database. I guess in your case this exception is wrapped intoUnexpectedRollbackException
. If version of the detached entity is0
, setting version column in the database to0
solves this.The real solution would be to increment version of the entity in the database when external software changes it. It would be consistent with optimistic locking strategy.