在OptimisticLockException之后重试方法时出错-org.postgresql.util.PSQLException:该语句已关闭 [英] Error when retrying method after OptimisticLockException - org.postgresql.util.PSQLException: This statement has been closed
问题描述
我有方法:
public void changeItemName(long id, String nmae) {
Item item = itemDAO.find(id);
item.setName(name);
try {
itemDAO.save(item);
} catch (RollbackException | OptimisticLockException | StaleStateException e) {
logger.warn("Retry method after " + e.getClass().getName());
itemDAO.clear();
changeItemName(id, name);
}
}
首先,我通过设置更高的版本来手动引发OptimisticLockException
,因此它会捕获块,清除EntityManager
并重试该方法.重试时,对象/实体会刷新并具有正确的版本,但我得到:
First, I manually provoke OptimisticLockException
by setting higher version, so it goes to catch block, clears EntityManager
and retries the method. When retrying, the object/entity is refreshed and has correct version but I get:
javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
Caused by: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
Caused by: org.postgresql.util.PSQLException: This statement has been closed.
at org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2653)
数据库模块(使用Guice 4.1.0):
Database module (using Guice 4.1.0):
public class DbModule extends PrivateModule {
@Override
public void configure() {
install(new JpaPersistModule("persistence-unit").properties(jpaProperties()));
...
Key<PersistFilter> key = Key.get(PersistFilter.class, ExamplePersistenceUnit.class);
bind(key).to(PersistFilter.class);
expose(key);
}
保存方法的实现(使用Hibernate 5.1.0.Final):
Save method implementation (using Hibernate 5.1.0.Final):
@Inject
protected EntityManager entityManager;
@Override
public void save(T entity) {
entityManager.getTransaction().begin();
entityManager.persist(entity);
entityManager.getTransaction().commit();
}
为什么会发生?
更新
经过一些调试后,我注意到:
After some debugging, I have noticed that:
- 第一种方法调用-我得到
OptimisticLockException
/StaleStateException
-没关系,这是有意提出并预期的 - 第二种方法调用,重试,我得到
Caused by: org.postgresql.util.PSQLException: This statement has been closed
-这是意外的 - 第三种方法调用,另一次重试-它运作良好,并成功保存到数据库中
- 1st method invocation - I get
OptimisticLockException
/StaleStateException
- that's ok, it was intentionally raised and expected - 2nd method invocation, retry, I get
Caused by: org.postgresql.util.PSQLException: This statement has been closed
- this one was unexpected - 3rd method invocation, another retry - it works well and saves to the DB successfully
所有3次使用相同的EntityManager entityManager
实例.
All 3 times, the same instance of EntityManager entityManager
is used.
推荐答案
我也遇到了相同的问题,并且在@Jonathan的评论的帮助下,我通过使用以下方法解决了该问题: @Retryable(include = {ObjectOptimisticLockingFailureException.class,JpaSystemException.class},backoff = @ Backoff(delay = 100))
I also encountered the same issue, and with the help of @Jonathan's comment, I solved it by using the: @Retryable(include = {ObjectOptimisticLockingFailureException.class, JpaSystemException.class}, backoff=@Backoff(delay = 100))
另请参见常见问题解答: Spring @Retryable-调用时如何记录?
See also good Q&A: Spring @Retryable - how to log when it is invoked?
这篇关于在OptimisticLockException之后重试方法时出错-org.postgresql.util.PSQLException:该语句已关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!