在OptimisticLockException之后重试方法时出错 - org.postgresql.util.PSQLException:此语句已关闭

时间:2017-05-04 10:44:11

标签: java hibernate jpa guice transactional

我有方法:

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,因此它将进入catch块,清除EntityManager并重试该方法。重试时,对象/实体会刷新并具有正确的版本,但我得到:

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):

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):

@Inject
protected EntityManager entityManager;

@Override
public void save(T entity) {
    entityManager.getTransaction().begin();
    entityManager.persist(entity);
    entityManager.getTransaction().commit();
}

为什么会这样?

更新

经过一些调试后,我注意到了:

  • 第一个方法调用 - 我得到OptimisticLockException / StaleStateException - 没关系,有意提出并预期
  • 第二次方法调用,重试,我得到Caused by: org.postgresql.util.PSQLException: This statement has been closed - 这是意外的
  • 第三个方法调用,另一个重试 - 它运行良好并成功保存到数据库

所有3次,使用EntityManager entityManager的相同实例。

1 个答案:

答案 0 :(得分:1)

我也遇到了同样的问题,在@Jonathan的评论的帮助下,我使用了: @Retryable(include = {ObjectOptimisticLockingFailureException.class,JpaSystemException.class},backoff = @ Backoff(delay = 100))

另请参见常见问题解答:Spring @Retryable - how to log when it is invoked?