【发布时间】:2011-04-10 07:04:06
【问题描述】:
我有一个使用 hibernate 3.1 和 JPA 注释的应用程序。它有一些具有 byte[] 属性的对象(大小为 1k - 200k)。它使用 JPA @Lob 注释,hibernate 3.1 可以在所有主要数据库上很好地读取这些 - 它似乎隐藏了 JDBC Blob 供应商的特性(应该这样做)。
@Entity
public class ConfigAttribute {
@Lob
public byte[] getValueBuffer() {
return m_valueBuffer;
}
}
当我们在 postgresql 中发现 hibernate 3.5 breaks (and won't fix) 这个注解组合时,我们不得不升级到 3.5(没有解决方法)。到目前为止,我还没有找到明确的解决方法,但我确实注意到,如果我只是删除 @Lob,它会使用 postgresql 类型 bytea(它有效,但仅在 postgres 上有效)。
annotation postgres oracle works on
-------------------------------------------------------------
byte[] + @Lob oid blob oracle
byte[] bytea raw(255) postgresql
byte[] + @Type(PBA) oid blob oracle
byte[] + @Type(BT) bytea blob postgresql
once you use @Type, @Lob seems to not be relevant
note: oracle seems to have deprecated the "raw" type since 8i.
我正在寻找一种方法来拥有一个可跨主要数据库移植的单个注释类(具有 blob 属性)。
- 注释 byte[] 属性的可移植方式是什么?
- 此问题是否已在某些最新版本的 hibernate 中得到修复?
更新: 在阅读了this blog 之后,我终于弄清楚了 JIRA 问题中的原始解决方法是:显然你应该删除 @Lob 并将属性注释为:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
但是,这对我来说不起作用 -- 我仍然得到 OID 而不是 bytea;然而,它确实适用于 JIRA 问题的作者,他似乎想要 oid。
在 A. Garcia 的回答之后,我尝试了这个组合,它实际上在 postgresql 上有效,但在 oracle 上无效。
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
我真正需要做的是控制@org.hibernate.annotations.Type 组合(@Lob + byte[] 被映射)到(在 postgresql 上)。
这是来自 MaterializedBlobType(sql 类型 Blob)的 3.5.5.Final 的 sn-p。根据 Steve 的博客,postgresql 希望您使用 Streams for bytea(不要问我为什么)和 postgresql 的自定义 Blob 类型用于 oids。另请注意,在 JDBC 上使用 setBytes() 也适用于 bytea(根据过去的经验)。所以这就解释了为什么 use-streams 没有影响他们都假设 'bytea'。
public void set(PreparedStatement st, Object value, int index) {
byte[] internalValue = toInternalFormat( value );
if ( Environment.useStreamsForBinary() ) {
// use streams = true
st.setBinaryStream( index,
new ByteArrayInputStream( internalValue ), internalValue.length );
}
else {
// use streams = false
st.setBytes( index, internalValue );
}
}
这会导致:
ERROR: column "signature" is of type oid but expression is of type bytea
更新 下一个合乎逻辑的问题是:“为什么不手动将表定义更改为 bytea”并保留 (@Lob + byte[])?这确实工作,直到你尝试存储一个空字节[]。 postgreSQL 驱动程序认为它是 OID 类型表达式,列类型是 bytea——这是因为 hibernate(正确地)调用 JDBC.setNull() 而不是 PG 驱动程序期望的 JDBC.setBytes(null)。
ERROR: column "signature" is of type bytea but expression is of type oid
hibernate 中的类型系统目前是“正在进行中的工作”(根据 3.5.5 弃用注释)。事实上,很多 3.5.5 代码已被弃用,很难知道在子类化 PostgreSQLDialect 时要查看什么)。
AFAKT,postgresql 上的 Types.BLOB/'oid' 应该映射到一些使用 OID 样式 JDBC 访问的自定义类型(即 PostgresqlBlobType 对象和 NOT MaterializedBlobType)。我从未真正成功地将 Blob 与 postgresql 一起使用,但我知道 bytea 只是像我所期望的那样工作。
我目前正在查看 BatchUpdateException - 驱动程序可能不支持批处理。
2004 年的精彩引述: “总结一下我的胡言乱语,我想说我们应该等待 JDBC 驱动程序在更改 Hibernate 之前正确执行 LOB。”
参考资料:
- https://forum.hibernate.org/viewtopic.php?p=2393203
- https://forum.hibernate.org/viewtopic.php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-4617
- http://postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- https://forums.hibernate.org/viewtopic.php?p=2203382&sid=b526a17d9cf60a80f13d40cf8082aafd
- http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs-oid-type/
【问题讨论】:
-
这个好像3.6已经修复了,不确定3.5.6; MaterializedBlobType 类从 3.5.5 > 3.6 完全重写。 OID 类型现在可以使用,因为它们更改了实现。
-
不错!我想知道 Jira 问题在跟踪这个重写(如果有的话)(也许重写是更深层次变化的结果)。如果可能的话,最好将 3.5 中的更改向后移植。如果不可能,那就是坏消息。
-
实际上我的测试第一次给了我一个误报(我知道我应该等待!)——它仍然没有修复,这个错误刚刚移动到 BlobTypeDescriptor。
-
谢谢。 @Type(type="org.hibernate.type.BinaryType") 为我工作了一个存储 PDF 文件的表。我使用 Intelligent Converters 中的 Oracle-To-PostgreSQL 将数据库从 Oracle 迁移到 Postgres,它自动从 BLOB 转换并插入到 BYTEA,但 BlobType 对我不起作用。
标签: java database hibernate postgresql blob