我有一个使用 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;
}
}
当我们发现 hibernate 3.5 断裂(不会修复)这个注释组合在 postgreql 中(没有变通方法)时,我们不得不升级到3.5。到目前为止,我还没有找到一个明确的修复方法,但是我注意到,如果删除@Lob,它将使用 postgreql 类型 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 属性) ,这是跨主要数据库可移植的。
更新: 在阅读了 这个博客之后,我终于弄明白了 JIRA 问题中最初的解决方案是什么: 显然,您应该删除@Lob 并将属性注释为:
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
byte[] getValueBuffer() {...
但是,这并不适用于 为了我——我仍然得到 OID 而不是 bytea; 但是对于 JIRA 问题的作者来说,它确实适用,因为他似乎希望使用 oid。
在 A.Garcia 给出答案之后,我尝试了这个组合,它实际上对 postgreql 有效,但对 Oracle 无效。
@Type(type="org.hibernate.type.BinaryType")
byte[] getValueBuffer() {...
我真正需要做的是控制@org。Hibernate 注解。键入组合(@Lob + byte []得到映射)到(on postgreql)。
下面是来自3.5.5的片段。最终版本来自 aterializedBlobType (sql 类型 Blob)。根据 Steve 的博客,postgreql 希望您使用 Streams 来表示 bytea (不要问我为什么) ,并使用 postgreql 的自定义 Blob 类型来表示 oid。另请注意,在 JDBC 上使用 setBytes ()也适用于 bytea (根据过去的经验)。因此,这就解释了为什么使用流没有影响,它们都假设“ 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中的大部分代码都已经被弃用了,因此很难知道在对 PostgreSQLDirecect 进行子类化时应该查看哪些代码)。
Postgreql 上的 Typees.BLOB/‘ OID’应该映射到一些使用 OID 样式 JDBC 访问的自定义类型(即 PostgreqlBlobType 对象和 NOT Materials alizedBlobType)。实际上,我从来没有成功地将 Blobs 与 postresql 结合使用,但是我知道 bytea 只是简单地按照 one/I 预期工作。
我目前正在查看 BatchUpdateException ——驱动程序可能不支持批处理。
2004年的一句名言: “总而言之,我认为在更改 Hibernate 之前,我们应该等待 JDBC 驱动程序正确执行 LOB。”
参考文献: