byte[] 的正确休眠注释 [英] proper hibernate annotation for byte[]

查看:27
本文介绍了byte[] 的正确休眠注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 hibernate 3.1 和 JPA 注释的应用程序.它有一些具有 byte[] 属性的对象(大小为 1k - 200k).它使用 JPA @Lob 注释,并且 hibernate 3.1 可以在所有主要数据库上很好地读取这些注释——它似乎隐藏了 JDBC Blob 供应商的特性(它应该这样做).

I have an application using hibernate 3.1 and JPA annotations. It has a few objects with byte[] attributes (1k - 200k in size). It uses the JPA @Lob annotation, and hibernate 3.1 can read these just fine on all major databases -- it seems to hide the JDBC Blob vendor peculiarities (as it should do).

@Entity
public class ConfigAttribute {
  @Lob
  public byte[] getValueBuffer() {
    return m_valueBuffer;
  }
}

我们不得不升级到 3.5,当我们发现 hibernate 3.5 中断(并且不会修复) 这个在 postgresql 中的注解组合(没有解决方法).到目前为止,我还没有找到明确的修复方法,但我确实注意到,如果我只是删除 @Lob,它会使用 postgresql 类型 bytea(它有效,但仅适用于 postgres).

We had to upgrade to 3.5, when we discovered that hibernate 3.5 breaks (and won't fix) this annotation combination in postgresql (with no workaround). I have not found a clear fix so far, but I did notice that if I just remove the @Lob, it uses the postgresql type bytea (which works, but only on 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 属性).

I am looking for a way to have a single annotated class (with a blob property) which is portable across major databases.

  • 注释 byte[] 属性的可移植方式是什么?
  • 此问题是否已在某些最新版本的 hibernate 中修复?

更新:在阅读了这篇博客后,我终于弄清楚了 JIRA 问题的原始解决方法是什么:显然,您应该删除 @Lob 并将该属性注释为:

Update: After reading this blog I have finally figured out what the original workaround in the JIRA issue was: Apparently you are supposed to drop @Lob and annotate the property as:

@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType") 
byte[] getValueBuffer() {...

然而,这对我不起作用——我仍然得到 OID 而不是 bytea;然而,它确实适用于 JIRA 问题的作者,他似乎想要 oid.

However, this does not work for me -- I still get OIDs instead of bytea; it did however work for the author of the JIRA issue, who seemed to want oid.

在 A. Garcia 的回答之后,我尝试了这个组合,它实际上适用于 postgresql,但不适用于 oracle.

After the answer from A. Garcia, I then tried this combo, which actually does work on postgresql, but not on oracle.

@Type(type="org.hibernate.type.BinaryType") 
byte[] getValueBuffer() {...

我真正需要做的是控制哪个@org.hibernate.annotations.Type 组合(@Lob + byte[] 被映射)到(在 postgresql 上).

What I really need to do is control which @org.hibernate.annotations.Type the combination (@Lob + byte[] gets mapped) to (on postgresql).

这是来自 MaterializedBlobType(sql 类型 Blob)的 3.5.5.Final 的片段.根据 Steve 的博客,postgresql 希望您将 Streams 用于 bytea(不要问我为什么)和 postgresql 的自定义 Blob 类型用于 oid.另请注意,在 JDBC 上使用 setBytes() 也适用于 bytea(根据过去的经验).所以这就解释了为什么 use-streams 没有影响他们都假设 'bytea'.

Here is the snippet from 3.5.5.Final from MaterializedBlobType (sql type Blob). According to Steve's blog, postgresql wants you to use Streams for bytea (don't ask me why) and postgresql's custom Blob type for oids. Note also that using setBytes() on JDBC is also for bytea (from past experience). So this explains why use-streams has no affect they both assume '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).

Update The next logical question is: "why not just change the table definitions manually to bytea" and keep the (@Lob + byte[])? This does work, UNTIL you try to store a null byte[]. Which the postgreSQL driver thinks is an OID type expression and the column type is bytea -- this is because hibernate (rightly) calls JDBC.setNull() instead of JDBC.setBytes(null) which PG driver expects.

ERROR: column "signature" is of type bytea but expression is of type oid

hibernate 中的类型系统目前是正在进行的工作"(根据 3.5.5 弃用评论).事实上,3.5.5 中的大部分代码都被弃用了,很难知道在对 PostgreSQLDialect 进行子类化时该看什么).

The type system in hibernate is currently a 'work in progress' (according to 3.5.5 deprecation comment). In fact so much of the 3.5.5 code is deprecated, it is hard to know what to look at when sub-classing the PostgreSQLDialect).

AFAKT,postgresql 上的 Types.BLOB/'oid' 应该映射到一些使用 OID 样式 JDBC 访问的自定义类型(即 PostgresqlBlobType 对象和 NOT MaterializedBlobType).我从来没有真正成功地将 Blob 与 postgresql 一起使用,但我知道 bytea 只是简单地工作/我所期望的.

AFAKT, Types.BLOB/'oid' on postgresql should be mapped to some custom type which uses OID style JDBC access (i.e. PostgresqlBlobType object and NOT MaterializedBlobType). I've never actually successfully used Blobs with postgresql, but I do know that bytea just simply works as one / I would expect.

我目前正在查看 BatchUpdateException - 驱动程序可能不支持批处理.

I am currently looking at the BatchUpdateException -- its possible that the driver doesn't support batching.

2004 年的精彩引述:总结一下我的散漫,我会说他们应该等待 JDBC 驱动程序正确执行 LOB,然后再更改 Hibernate."

Great quote from 2004: "To sum up my ramblings, I'd say they we should wait for the JDBC driver to do LOBs properly before changing Hibernate."

参考:

推荐答案

注释 byte[] 属性的可移植方式是什么?

What is the portable way to annotate a byte[] property?

这取决于你想要什么.JPA 可以保留未注释的 byte[].来自 JPA 2.0 规范:

It depends on what you want. JPA can persist a non annotated byte[]. From the JPA 2.0 spec:

Basic 注释是最简单的到数据库列的映射类型.可以应用 Basic 注释到持久属性或实例以下任何一个变量类型:Java 原语、类型、包装器原始类型,java.lang.String,java.math.BigInteger,java.math.BigDecimal,java.util.Date,java.util.Calendar, java.sql.Date,java.sql.Time, java.sql.Timestamp,byte[]Byte[]char[]Character[]、枚举和任何其他实现 Serializable 的类型.如第 2.8 节所述,使用Basic 注释是可选的用于持久字段和属性这些类型.如果基本没有为此类指定注释字段或属性,默认值将应用基本注释.

11.1.6 Basic Annotation

The Basic annotation is the simplest type of mapping to a database column. The Basic annotation can be applied to a persistent property or instance variable of any of the following types: Java primitive, types, wrappers of the primitive types, java.lang.String, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, byte[], Byte[], char[], Character[], enums, and any other type that implements Serializable. As described in Section 2.8, the use of the Basic annotation is optional for persistent fields and properties of these types. If the Basic annotation is not specified for such a field or property, the default values of the Basic annotation will apply.

并且 Hibernate 会将它默认"映射到 SQL VARBINARY(或 SQL LONGVARBINARY 取决于 Column 的大小?)PostgreSQL 用 bytea 处理.

And Hibernate will map a it "by default" to a SQL VARBINARY (or a SQL LONGVARBINARY depending on the Column size?) that PostgreSQL handles with a bytea.

但是如果您希望将 byte[] 存储在大对象中,则应该使用 @Lob.来自规范:

But if you want the byte[] to be stored in a Large Object, you should use a @Lob. From the spec:

A Lob 注释指定一个持久属性或字段应该是作为一个大对象持久化到一个数据库支持的大对象类型.便携式应用程序应该使用Lob 映射到 a 时的注解数据库Lob 类型.Lob 注释可以与基本注释或带有ElementCollection 注释时元素集合值是基本的类型.Lob 可以是二进制或字符类型.Lob 类型是从类型推断持久的领域或财产,以及,除了字符串和字符类型,默认为 Blob.

11.1.24 Lob Annotation

A Lob annotation specifies that a persistent property or field should be persisted as a large object to a database-supported large object type. Portable applications should use the Lob annotation when mapping to a database Lob type. The Lob annotation may be used in conjunction with the Basic annotation or with the ElementCollection annotation when the element collection value is of basic type. A Lob may be either a binary or character type. The Lob type is inferred from the type of the persistent field or property and, except for string and character types, defaults to Blob.

Hibernate 会将它映射到 SQL BLOB,PostgreSQL 用 oid 处理它.

And Hibernate will map it to a SQL BLOB that PostgreSQL handles with a oid .

这是否在某些最新版本的 hibernate 中修复?

Is this fixed in some recent version of hibernate?

嗯,问题是我不知道问题到底是什么.但我至少可以说,自 3.5.0-Beta-2(这是在 3.5.x 分支中引入更改的地方)以来没有任何变化.

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.

但我对HH-4876HHH-4617 和 PostgreSQL 和 BLOBs(在 PostgreSQLDialect 的 javadoc 中提到)是你应该设置以下属性

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 property

hibernate.jdbc.use_streams_for_binary=false

如果你想使用 oidbyte[]@Lob (这是我的理解,因为 VARBINARY 不是您想要的 Oracle).你试过这个吗?

if you want to use oid i.e. byte[] with @Lob (which is my understanding since VARBINARY is not what you want with Oracle). Did you try this?

作为替代方案,HHH-4876 建议使用已弃用的 PrimitiveByteArrayBlobType 以获取旧行为(Hibernate 3.5 之前).

As an alternative, HHH-4876 suggests using the deprecated PrimitiveByteArrayBlobType to get the old behavior (pre Hibernate 3.5).

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆