gpt4 book ai didi

java - Hibernate 和 Postgres 大对象 - 在实体 finalize() 方法中释放 Blob 资源

转载 作者:搜寻专家 更新时间:2023-11-01 03:24:13 25 4
gpt4 key购买 nike

我有一个应用程序使用 EJB 3.0 和 Hibernate 在 JBoss 4.2.3 AS 上运行,事务由 EJB 控制。

我遇到的问题是 Postgres 日志中有几条关于大对象的消息,例如“错误:无效的大对象描述符:0”,有时还有“错误:大对象 488450 不存在”。结果是在应用程序中一切正常,但有时(并非总是)Postgres 无法在 hibernate 提交后提交事务(在主 EJB 中的所有代码调用的方法被执行之后)。

我调查了遗留代码并找到了代表数据库中文件存储的所有实体的父类(super class)。在此类中,文件由 Blob 属性表示,并由 getBinaryStream() 方法使用。我发现奇怪的是这个类的 finalize() 方法中的内容如下:

@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "BIN_CONTENT", nullable = true, updatable = true)
protected Blob content;

@Override
protected void finalize() throws Throwable {
if (this.content != null) {
try {
IOUtils.closeQuietly(this.content.getBinaryStream());
} catch (Exception e) {
logger.severe("Error finalizing Blob stream");
}
try {
this.content.free();
} catch (AbstractMethodError e) {
} catch (SQLFeatureNotSupportedException e) {
} catch (UnsupportedOperationException e) {
} catch (Throwable e) {
logger.severe("Error finalizing Blob stream");
}
this.content = null;
}
super.finalize();
}

在我评论这段代码后,一切似乎都运行良好。问题是:那有必要吗?我想了解由于执行导致数据库端错误的代码内部发生了什么。

最佳答案

您提供的代码存在几个问题。

第一个问题是finalize() 时机。

java.sql.Blob 实现取决于 jdbc 驱动程序,通常实现类仅存储 blob 的标识符以及访问内容的时间(使用 getBinaryStream()例如)执行另一个对数据库的调用。这意味着在 getBinaryStream() 被调用的那一刻,用于获取 blob 的连接应该仍然打开。但是 JVM 在调用 finalize 时不提供任何保证,因此在 finalize 中访问 Blob 是不正确的。

我不确定 PostgreSQL jdbc 驱动程序是否将此逻辑用于 blob,但我确定 java.sql.Array 实现具有此限制(即您不能调用数组的方法连接关闭后)。

第二个问题是,尽管 blob 映射被定义为惰性映射,即使客户端不使用它,blob 字段也将始终由 finalize() 加载。

通常,在使用 blob 时,客户端有责任执行清理。 blob 的使用模式是:

try {
blob = entity.getContent();
// ... use blob
} finally {
// ... do blob cleanup
}

关于java - Hibernate 和 Postgres 大对象 - 在实体 finalize() 方法中释放 Blob 资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19452614/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com