我有一个使用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;
}
}
当我们发现休眠3.5 破坏了(并且不会修复) postgresql中的这个注释组合时(没有解决方法),我们不得不升级到3.5 。到目前为止,我还没有找到明确的修复程序,但是我确实注意到,如果我只是删除@Lob,它将使用postteasql类型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 []属性的可移植方式是什么?
- 在最新的休眠版本中已解决此问题吗?
更新: 阅读此博客后,我终于弄清楚了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版本的代码段。根据Steve的博客,postgresql希望您将流用于bytea(不要问我为什么),并将postgresql的自定义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 [])?这确实工作,UNTIL你尝试存储空字节[]。postgreSQL驱动程序认为是OID类型表达式,列类型是bytea,这是因为休眠(正确地)调用JDBC.setNull()而不是PG驱动程序期望的JDBC.setBytes(null)。
ERROR: column "signature" is of type bytea but expression is of type oid
休眠中的类型系统当前是一个“进行中的工作”(根据3.5.5弃用注释)。实际上,不赞成使用3.5.5的大部分代码,在对PostgreSQLDialect进行子类化时,很难知道要看什么。
AFAKT,Postgresql上的Types.BLOB /'oid'应该映射到使用OID样式JDBC访问的某些自定义类型(即PostgresqlBlobType对象和NOT MaterializedBlobType)。我从未真正将Blobs与postgresql一起成功使用,但是我确实知道,bytea只能像我期望的那样工作。
我目前正在查看BatchUpdateException-驱动程序可能不支持批处理。
2004年的一句名言:“总结一下,我想说他们应该在更改Hibernate之前等待JDBC驱动程序正确执行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/