Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在OptimisticLockException-org.postgresql.util.PSQLException之后重试方法时出错:此语句已关闭_Java_Hibernate_Jpa_Guice_Transactional - Fatal编程技术网

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

Java 在OptimisticLockException-org.postgresql.util.PSQLException之后重试方法时出错:此语句已关闭,java,hibernate,jpa,guice,transactional,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) { l

我有一个方法:

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

为什么会这样

更新

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

  • 第一次方法调用-我得到了
    OptimisticLockException
    /
    StaleStateException
    -没关系,它是故意引发的,并且是预期的
  • 第二次方法调用,重试,我得到由以下原因引起的
    :org.postgresql.util.PSQLException:此语句已关闭
    -此语句意外
  • 第三次方法调用,另一次重试-它运行良好,并成功保存到数据库

这三次都使用了同一个实例
EntityManager EntityManager

我也遇到了同样的问题,在@Jonathan评论的帮助下,我使用以下方法解决了这个问题: @可重试(包括{ObjectOptimisticLockingFailureException.class,JpaSystemException.class},退避=@backoff(延迟=100))


另请参见好的问答:

itemDAO.clear()做什么?您如何管理您的交易?
@注入了什么?(通常,
EntityManager
被注入
@PersistenceUnit
)--当
PreparedStatement
被(重新)使用,但底层连接已经关闭时,会出现错误消息。itemDAO.clear()不执行EntityManager.clear()。在执行第二个itemDAO.find(id)时,我使用它从数据库获取最新的数据。感谢您在PSQLException之后第三次尝试更新!我们使用乐观锁定将Spring重试包装在事务周围。使用
@Retryable(include={ObjectOptimisticLockingFailureException.class,JpaSystemException.class},maxturets=4)
我们所有的并发更新测试都通过了。如果我们不重试JPAsyStemeException(它将PSQLException包装为关闭的连接),那么每次重试时我们的测试都会失败,并出现closed语句错误。
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);
}
@Inject
protected EntityManager entityManager;

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