byte[] 的正确休眠注释
我有一个使用 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 破坏(并且无法修复) postgresql 中的这个注释组合(没有解决方法)。到目前为止,我还没有找到明确的修复方法,但我确实注意到,如果我只是删除 @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[] 属性的可移植方法是什么?
- 这个问题在最新版本的休眠中修复了吗?
更新: 阅读此博客后,我终于弄清楚了 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 希望你使用 Streams 作为 bytea(不要问我为什么),并使用 postgresql 的自定义 Blob 类型作为 oid。另请注意,在 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 对象而不是 MaterializedBlobType)。我从未真正成功地将 Blob 与 postgresql 一起使用,但我确实知道 bytea 只是简单地工作/我期望的那样。
我目前正在查看 BatchUpdateException - 驱动程序可能不支持批处理。
2004 年的精彩引言: “总而言之,我想说的是,我们应该等待 JDBC 驱动程序正确执行 LOB,然后再更改 Hibernate。”
参考文献:
- https://forum.hibernate.org/viewtopic。 php?p=2393203
- https://forum.hibernate.org/viewtopic。 php?p=2435174
- http://hibernate.atlassian.net/browse/HHH-第4617
- 章postgresql.1045698.n5.nabble.com/Migration-to-Hibernate-3-5-final-td2175339.html
- https://jira.springframework.org/browse/SPR-2318
- “ http://virgo47.wordpress.com/2008/ 06/13/jpa-postgresql-and-bytea-vs-oid-type/" rel="noreferrer">http://virgo47.wordpress.com/2008/06/13/jpa-postgresql-and-bytea-vs -oid-类型/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
Hibernate 6+、javaee 9+
Hibernate 6+, javaee 9+
在 Postgres 上,@Lob 会破坏 byte[],因为它试图将其保存为 oid,对于 String 也会出现同样的问题。下面的代码在 postgres 上被破坏,而 postgres 在 oracle 上运行得很好。
,
为了解决上面的问题
在 postgres 上写了下面的自定义 hibernate.dialect现在在 hibernate XYZ 中配置自定义方言
是包名称。
现在工作正常了。
注意-我的 Hibernate 版本 - 5.2.8.Final
Postgres 版本 - 9.6.3
On Postgres @Lob is breaking for byte[] as it tries to save it as oid, and for String also same problem occurs. Below code is breaking on postgres which is working fine on oracle.
and
In order to fix above on postgres have written below custom hibernate.dialect
Now configure custom dialect in hibernate
X.Y.Z is package name.
Now it working fine.
NOTE- My Hibernate version - 5.2.8.Final
Postgres version- 9.6.3
我通过使用 Postgres 的 XML 文件覆盖注释来实现它。为 Oracle 保留注释。在我看来,在这种情况下,我们最好使用 xml 映射来覆盖这个麻烦实体的映射。我们可以使用 xml 映射覆盖单个/多个实体。因此,我们将为主要支持的数据库使用注释,并为每个其他数据库使用 xml 文件。
注意:我们只需要重写一个类,所以这并不是什么大问题。
从我的例子中阅读更多内容
使用 XML 覆盖注释的示例
I got it work by overriding annotation with XML file for Postgres. Annotation is kept for Oracle. In my opinion, in this case it would be best we override the mapping of this trouble-some enity with xml mapping. We can override single / multiple entities with xml mapping. So we would use annotation for our mainly-supported database, and a xml file for each other database.
Note: we just need to override one single class , so it is not a big deal.
Read more from my example
Example to override annotation with XML
感谢贾斯汀、帕斯卡引导我走向正确的方向。我在使用 Hibernate 3.5.3 时也遇到了同样的问题。您的研究和对正确课程的指导帮助我识别了问题并进行了修复。
为了让那些仍然坚持使用 Hibernate 3.5 并使用 oid + byte[] + @LoB 组合的人受益,以下是我为解决该问题所做的工作。
我创建了一个自定义 BlobType,它扩展了 MaterializedBlobType,并使用 oid 样式访问覆盖了 set 和 get 方法。
向 Hibernate 注册 CustomBlobType。以下是我为实现这一目标所做的事情。
Thanks Justin, Pascal for guiding me to the right direction. I was also facing the same issue with Hibernate 3.5.3. Your research and pointers to the right classes had helped me identify the issue and do a fix.
For the benefit for those who are still stuck with Hibernate 3.5 and using oid + byte[] + @LoB combination, following is what I have done to fix the issue.
I created a custom BlobType extending MaterializedBlobType and overriding the set and the get methods with the oid style access.
Register the CustomBlobType with Hibernate. Following is what i did to achieve that.
这取决于你想要什么。 JPA 可以持久保存未注释的
byte[]
。来自 JPA 2.0 规范:Hibernate 会将其“默认”映射到 PostgreSQL 处理的 SQL
VARBINARY
(或 SQLLONGVARBINARY
,具体取决于Column
大小?)与bytea
。但如果您希望将
byte[]
存储在大对象中,则应该使用@Lob
。从规格来看:Hibernate 会将其映射到 PostgreSQL 使用
oid
处理的 SQLBLOB
。
嗯,问题是我不知道问题到底是什么。但我至少可以说,自 3.5.0-Beta-2(这是引入更改的地方)以来,3.5.x 分支中没有任何变化。
但我对诸如 HHH-4876、HHH-4617 和
PostgreSQLAndBLOBs" rel="noreferrer">PostgreSQL 和 BLOBs (在 PostgreSQLDialect 的 javadoc 中提到)是,如果你想使用 oid, 即
byte[]
和@Lob
(这是我的理解,因为VARBINARY
不是您想要的 Oracle)。你尝试过这个吗?作为替代方案,HHH-4876 建议使用已弃用的
PrimitiveByteArrayBlobType
以获取旧行为(Hibernate 3.5 之前的版本)。参考
资源
It depends on what you want. JPA can persist a non annotated
byte[]
. From the JPA 2.0 spec:And Hibernate will map a it "by default" to a SQL
VARBINARY
(or a SQLLONGVARBINARY
depending on theColumn
size?) that PostgreSQL handles with abytea
.But if you want the
byte[]
to be stored in a Large Object, you should use a@Lob
. From the spec:And Hibernate will map it to a SQL
BLOB
that PostgreSQL handles with aoid
.
Well, the problem is that I don't know what the problem is exactly. But I can at least say that nothing has changed since 3.5.0-Beta-2 (which is where a changed has been introduced)in the 3.5.x branch.
But my understanding of issues like HHH-4876, HHH-4617 and of PostgreSQL and BLOBs (mentioned in the javadoc of the
PostgreSQLDialect
) is that you are supposed to set the following propertyif you want to use
oid
i.e.byte[]
with@Lob
(which is my understanding sinceVARBINARY
is not what you want with Oracle). Did you try this?As an alternative, HHH-4876 suggests using the deprecated
PrimitiveByteArrayBlobType
to get the old behavior (pre Hibernate 3.5).References
Resources
O'reilly Enterprise JavaBeans 3.0 的内容如下
这里是 PostgreSQLDialect 源代码
那么你可以做什么
覆盖 PostgreSQLDialect 如下
现在只需定义你的自定义方言
并使用你的便携式 JPA @Lob 注释
UPDATE
这里已提取 此处
...
which可以在此处进行解释
...
有趣的是,当他将 Types.BOLB 映射为 bytea 时(请参阅 CustomPostgreSQLDialect),他得到
插入或更新时
Here goes what O'reilly Enterprise JavaBeans, 3.0 says
Here goes PostgreSQLDialect source code
So what you can do
Override PostgreSQLDialect as follows
Now just define your custom dialect
And use your portable JPA @Lob annotation
UPDATE
Here has been extracted here
...
which can be explained here
...
Interesting is because when he maps Types.BOLB as bytea (See CustomPostgreSQLDialect) He get
when inserting or updating
我正在使用 Hibernate 4.2.7.SP1 和 Postgres 9.3,以下内容对我有用:
因为 Oracle 对此没有任何问题,对于 Postgres,我使用自定义方言:
我认为这个解决方案的优点是,我可以保留休眠罐子未受影响。
有关 Hibernate 的更多 Postgres/Oracle 兼容性问题,请参阅我的 博客文章。
I'm using the Hibernate 4.2.7.SP1 with Postgres 9.3 and following works for me:
as Oracle has no trouble with that, and for Postgres I'm using custom dialect:
the advantage of this solution I consider, that I can keep hibernate jars untouched.
For more Postgres/Oracle compatibility issues with Hibernate, see my blog post.
我终于成功了。然而,它扩展了 A. Garcia 的解决方案,因为问题在于 hibernate 类型 MaterializedBlob 类型仅映射 Blob > 。 bytea 还不够,我们需要替代 MaterializedBlobType,它可以与 hibernates 损坏的 blob 支持一起使用。该实现仅适用于 bytea,但也许 JIRA 问题中想要 OID 的人可以贡献一个 OID 实现。
遗憾的是,在运行时替换这些类型是一件痛苦的事情,因为它们应该是方言的一部分。
如果这个 JIRA 增强进入 3.6 就有可能。
其中大部分可能是静态的(getBinder() 真的需要一个新实例吗?),但我不太了解 hibernate 内部,所以这主要是复制+粘贴+修改。
I have finally got this working. It expands on the solution from A. Garcia, however, since the problem lies in the hibernate type MaterializedBlob type just mapping Blob > bytea is not sufficient, we need a replacement for MaterializedBlobType which works with hibernates broken blob support. This implementation only works with bytea, but maybe the guy from the JIRA issue who wanted OID could contribute an OID implementation.
Sadly replacing these types at runtime is a pain, since they should be part of the Dialect.
If only this JIRA enhanement gets into 3.6 it would be possible.
Much of this could probably be static (does getBinder() really need a new instance?), but I don't really understand the hibernate internal so this is mostly copy + paste + modify.
我通过添加 @Lob 注释解决了我的问题,该注释将在 oracle 中创建 byte[] 作为 blob ,但此注释会将字段创建为 oid ,而无法正常工作,为了使 byte[] 创建为 bytea 我创建了客户方言postgres 如下
还需要覆盖方言
spring.jpa.properties.hibernate.dialect=com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
的参数,可以找到更多提示: https://dzone.com/articles/postgres-and-oracle
i fixed My issue by adding the annotation of @Lob which will create the byte[] in oracle as blob , but this annotation will create the field as oid which not work properly , To make byte[] created as bytea i made customer Dialect for postgres as below
Also need to override parameter for the Dialect
spring.jpa.properties.hibernate.dialect=com.ntg.common.DBCompatibilityHelper.PostgreSQLDialectCustom
more hint can be found her : https://dzone.com/articles/postgres-and-oracle