java - 重试 repository.save() 时出现 StaleObjectStateException
问题描述
几个月来我一直在为一个问题苦苦挣扎。我需要从我的数据库中复制一组对象/文件并将其保存为新实例。比如说一个有很多依赖实体的学生实体。所有依赖实体中都有很多文件。所以我制作了对象的副本并调用 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:行被另一个事务更新或删除(或未保存值映射不正确)
我必须重新保存这个记录。我怎样才能做到这一点。我怎样才能回滚上一个。我是冬眠的初学者。我真的在这个问题上苦苦挣扎。请帮忙
解决方案
您的流程似乎试图在单个事务中执行此操作。我建议不要这样做,而是在多个较小的交易中这样做。这样您就可以从上次失败的地方继续工作,这很重要,因为看起来连接异常是由于连接打开时间过长或某些网络问题造成的。我不知道您的事务和持久性上下文管理,但是发生异常后,您应该摆脱持久性上下文(EntityManager
/ Session
)并创建一个新的。
推荐阅读
- python - 如何使用 anaconda 为 python 安装 google.cloud automl_v1beta1?
- amazon-web-services - 如何将 AWS CodeBuild 配置为仅在推送到主分支时进行构建?
- symfony - 如何用@IsGranted 覆盖Symfony 中的控制器方法的访问控制部分?
- google-assistant-sdk - 如果我询问位置等,我无法从 Google 助理 API 获得补充显示文本
- php - 使用 preg_replace 删除空格会在 php 中的字符串中输出无法识别的字符
- javascript - tfjs mode.predict 返回相同的结果
- android - 寻找解释设计或我的困惑
- c# - 如何统一模拟键盘按键?
- laravel - 在 Laravel 中验证后获取转发器字段
- matlab - 如何通过 Matlab 中的帧索引读取特定视频帧?