JPA并发问题“在批量发布时,它仍然包含JDBC语句” [英] JPA concurrency issue "On release of batch it still contained JDBC statements"

查看:4251
本文介绍了JPA并发问题“在批量发布时,它仍然包含JDBC语句”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个并发问题,我试图用一个while循环解决,它试图多次保存一个实体,直到它达到最大重试次数。我想避免谈论是否有其他方法来解决这个问题。我有其他的Stackoverflow的文章。 :)长话短说:对派生的列有一个唯一的约束,并包含一个数字部分,该部分不断增加以避免冲突。在一个循环中,我:


  1. select max(some_value)

  2. 递增结果
  3. >
  4. 尝试使用此新结果保存新对象
  5. 显式刷新实体,如果由于唯一索引而失败,我会捕获DataAccessException。 li>

除了当循环返回到第1步并尝试选择时,所有这些似乎都可以工作,我得到:

  17:20:46,111 INFO [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl](http-localhost / 127.0.0.1:8080- 3)HHH000010:在批量发布时,它仍然包含JDBC语句
17:20:46,111 INFO [my.Class](http-localhost / 127.0.0.1:8080-3)MESSAGE =无法保存到数据库。将重试(现在重试计数:9)例外:无法执行语句; SQL [n / a];约束[SCHEMA_NAME.UNIQUE_CONSTRAINT_NAME];嵌套异常是org.hibernate.exception.ConstraintViolationException:无法执行语句

和a新的异常被捕获。看起来像是导致唯一约束冲突的第一次刷新并引发 DataAccessException 不会清除实体管理器的批处理。处理这个问题的适当方法是什么?我在JPA中使用Spring并且没有直接访问实体管理器的权限。我想我可以注入它,如果我需要它,但这是一个痛苦的解决这个问题。 解决方案

你不能这样做 - 一次您刷新某些内容并失败并抛出异常时,事务将被标记为回滚。这意味着你没有处理异常并继续进行,最终会回滚。
事实上,抛出异常并不重要 - 默认情况下,Spring的事务管理器将在每个未经检查的异常处回滚。
您可以通过在 @Transactional 注释中专门定义一个 noRollbackFor 来克服它(假设您使用了注释驱动程序事务)

编辑 - 在违反此约束的情况下,它也不会帮助您,因为事务可能会在数据库级别标记为回滚。 p>

I have a a concurrency issue I tried to solve with a while loop that attempts to save an entity multiple times until it hits some max retry count. I'd like to avoid talking about whether or not there are other ways to solve this problem. I have other Stackoverflow posts about that. :) Long story short: there's a unique constraint on a column that is derived and includes a numeric portion that keeps incrementing to avoid collisions. In a loop, I:

  1. select max(some_value)
  2. increment the result
  3. attempt to save new object with this new result
  4. explicitly flush the entity and, if that fails because of the unique index, I catch a DataAccessException.

All of this seems to work except when the loop goes back to step 1 and tries to select, I get:

17:20:46,111 INFO  [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] (http-localhost/127.0.0.1:8080-3) HHH000010: On release of batch it still contained JDBC statements
17:20:46,111 INFO  [my.Class] (http-localhost/127.0.0.1:8080-3) MESSAGE="Failed to save to database. Will retry (retry count now at: 9) Exception: could not execute statement; SQL [n/a]; constraint [SCHEMA_NAME.UNIQUE_CONSTRAINT_NAME]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"

And a new Exception is caught. It seems like the first flush that causes the unique constraint violation and throws the DataAccessException doesn't clear the entity manager's batch. What's the appropriate way to deal with this? I'm using Spring with JPA and don't have direct access to the entity manager. I guess I could inject it if I need it but that's a painful solution to this problem.

解决方案

You cannot do that - once you flush something and it fails and an exception is thrown, the transaction will be marked as roll back. That means it doesnt matter that you catch the exception and proceed, you'll end up with a rollback. Actually it doesnt matter at all what exception was thrown - by default Spring's transaction manager will rollback on every unchecked exception. You can overcome it by specifically defining a noRollbackFor on the @Transactional annotation (providing you are using annotation driver transactions)

Edit - it also won't help you in case of this constraint violation, since the transaction will be probably marked as rollback at the database level.

这篇关于JPA并发问题“在批量发布时,它仍然包含JDBC语句”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆