【问题标题】:StaleObjectStateException when retrying repository.save()重试 repository.save() 时出现 StaleObjectStateException
【发布时间】:2021-04-22 14:43:02
【问题描述】:

几个月来,我一直在为一个问题苦苦挣扎。我需要从我的数据库中复制一组对象/文件并将其保存为新实例。比如说一个有很多依赖实体的学生实体。所有依赖实体中都有很多文件。所以我制作了对象的副本并调用 repositiry.save()。如果成功,此保存的整个过程最多需要 40 分钟。但在一些随机运行中它会抛出

java.io.IOException: Closed Connection
    at oracle.jdbc.driver.OracleBlobInputStream.needBytes(OracleBlobInputStream.java:204)
    at oracle.jdbc.driver.OracleBufferedStream.readInternal(OracleBufferedStream.java:169)
    at oracle.jdbc.driver.OracleBufferedStream.read(OracleBufferedStream.java:143)
    at oracle.jdbc.driver.OracleBufferedStream.read(OracleBufferedStream.java:132)
    at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1158)
    at org.apache.commons.io.IOUtils.copy(IOUtils.java:878)
    at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1135)
    at org.apache.commons.io.IOUtils.copy(IOUtils.java:854)
    at com.*.*.*.*.hibernate.BlobUserType.nullSafeSet(BlobUserType.java:209)
    at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:160)

下面给出nullSafeSet方法

@Override
    public void nullSafeSet(PreparedStatement ps, Object value, int index, SharedSessionContractImplementor session)
            throws HibernateException, SQLException {

        
        if (value == null) {
            ps.setNull(index, Types.BLOB);
        } else {
            if (value instanceof FileUploadBlob) {
                FileUploadBlob fileUploadBlob = (FileUploadBlob) value;
                InputStream inputStream = fileUploadBlob.getBinaryStream();
                DatabaseMetaData dbMetaData = session.connection().getMetaData();
                String dbProductName = dbMetaData.getDatabaseProductName();
                if (dbProductName.toUpperCase().contains("ORACLE")) {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    try {
                        IOUtils.copy(inputStream, baos);
                        InputStream is = new ByteArrayInputStream(baos.toByteArray());
                        ps.setBlob(index, is); // assume JDBC 3.0
                        
                        inputStream.close();
                        baos.close();
                    } catch (IOException e) {
                        LOG.error("Clone process interrupted due to IOException thrown :", e);
                    } catch (Exception e) {
                        LOG.error("Clone process interrupted due to Exception thrown :", e);
                    }
                }
            } else if (value instanceof Blob) {
                ps.setBlob(index, (Blob) value);
            } else {
                LOG.warn("Unknown BLOB type");
            }
        }
            
    }

我已经更改了一些配置等等,但没有任何效果。

现在作为控制器的解决方法,我发现异常并重试保存相同的对象(保存失败)

导致错误

org.hibernate.StaleObjectStateException: 行被更新或删除 另一笔交易(或未保存值映射不正确)

我必须重新保存这条记录。我怎样才能做到这一点。我怎样才能回滚上一个。我是冬眠的初学者。我真的在这个问题上苦苦挣扎。请帮忙

【问题讨论】:

  • 尽量只使用休眠映射来保存对象(我的意思是在 ORM 中使用类关联映射)
  • TBH 我不会想到使用 Hibernate 执行这样的任务。为什么不创建执行 SQL 的批处理作业?

标签: java hibernate database-connection rollback staleobjectstateexception


【解决方案1】:

您的进程似乎试图在单个事务中执行此操作。我建议不要这样做,而是在多个较小的交易中这样做。这样,您可以从上次失败的地方继续工作,这很重要,因为看起来连接异常是由于连接打开时间过长或某些网络问题造成的。我不知道你的事务和持久化上下文管理,但是发生异常后,你应该摆脱持久化上下文(EntityManager/Session)并创建一个新的。

【讨论】:

    猜你喜欢
    • 2013-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    相关资源
    最近更新 更多