我有一个使用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.5breaks (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中修复了这个问题吗?

Update: 在阅读了this blog之后,我终于明白了JIRA问题中最初的解决方法是什么:显然,您应该删除@Lob并将该属性注释为:

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

然而,这不能for me起作用--我仍然得到OID,而不是BYTEA;但是,它确实对JIRA问题的作者有效,他似乎想要OID.

在A.Garcia给出答案后,我try 了这个组合,它实际上对postgresql有效,但对oracle无效.

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

我真正需要做的是控制哪个@org.冬眠注释.键入组合(@Lob+byte[]被映射)到(在postgresql上).


下面是3.5.5中的代码片段,最终来自MaterializedBlobType(SQL类型Blob).根据Steve的博客,PostgreSQL希望您将Streams用于byTea(不要问我为什么),并将PostgreSQL的自定义Blob类型用于OID.还要注意,在JDBC上使用setBytes()也是为了byteA(根据过go 的经验).这就解释了为什么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

Update

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

Hibernate中的类型系统目前是一个"正在进行中的工作"(根据3.5.5反对意见).事实上,3.5.5代码中的很多内容都被弃用了,以至于很难知道当子类化PostgreSQLDialect时要看什么).

阿法克,类型.postgresql上的BLOB/'oid'应该映射到使用oid样式JDBC访问的某个自定义类型(即PostgresqlBlobType对象和非materialized BlobType).我从来没有在postgresql中成功地使用过Blob,但我知道bytea只是像我预期的那样工作.

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


2004年的名言:

References:

推荐答案

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

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

11.1.6基本注释

Basic批注是最简单的 映射到数据库列的类型. 可以应用Basic注释 到持久属性或实例 变量为以下任一变量 类型:Java原语、类型、包装器 在原始类型中, java.lang.Stringjava.math.BigIntegerjava.math.BigDecimaljava.util.Datejava.util.Calendar,java.sql.Datejava.sql.Time,java.sql.Timestamp110, 111char[]Character[]、枚举和任何其他 实现Serializable的类型. 如第2.8节所述,使用 Basic个批注中的一个是可选的 对于持久字段和属性 这些类型中的一种.如果基本的 未为此类对象指定批注 字段或属性,默认值 将适用于基本注释的.

Hibernate将把一个it"默认"映射到一个SQL VARBINARY(或者一个SQL LONGVARBINARY,具体取决于Column的大小?)PostgreSQL处理的是bytea.

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

11.1.24 LOB注释

Lob注释指定

Hibernate会将其映射到PostgreSQL用oid处理的SQLBLOB .

在某些最新版本的Hibernate中修复了这个问题吗?

问题是我不知道到底是什么问题.但我至少可以说,自3.5版本中的3.5.0-Beta-2(也就是引入了一个变化的版本)以来,一切都没有改变.x分支.

但我对HHH-4876HHH-4617PostgreSQL and BLOBs(在PostgreSQLDialect的javadoc中提到)等问题的理解是,应该设置以下属性

hibernate.jdbc.use_streams_for_binary=false

如果你想使用oid,即byte[]@Lob(这是我的理解,因为VARBINARY不是你想要的甲骨文).你试过这个吗?

作为替代方案,HHH-4876建议使用不推荐的PrimitiveByteArrayBlobType来获得旧的行为(pre Hibernate 3.5).

参考文献

  • JPA 2.0规范
    • 第2.8节"非关系字段或属性的映射默认值"
    • 第11.1.6节"基本注释"
    • 第11.1.24节"LOB批注"

资源

Database相关问答推荐

触发器作为完整性的判断约束

芭蕾舞女演员坚持 1:N 关系

您是否遇到过 SQL Server 因为引用了太多表而无法执行的查询?

用于存储人与聊天消息的数据库设计

使用python为组中的每个元素添加一个序列号

用于为 Android 设计 SQLite 数据库的开发人员工具

何时将数据库称为嵌入式数据库?

只用一个 save() 插入多行

SQL Select 用字符串替换整数

Zend 框架 - 为什么我应该使用数据映射器/Db_Table_Row?

我需要在这个 Django 模型中添加一个 db_index 吗?

返回 DataSet/DataTable 的 PowerShell 函数中的奇怪行为

NameError:设置更改为 mysql 后未定义名称_mysql

在 Rails 中销毁/删除数据库

有没有一种简单的方法来告诉 alembic 迁移到特定版本?

日期格式的 Oracle SQL 查询

如何使用 JPA 注释创建连接表?

试图在我的环境中设置 Postgres,但似乎无法获得 intidb 的权限

Web 应用程序的文件存储:文件系统、数据库和 NoSQL 引擎

在 UI 中执行业务逻辑的单元测试数据库应用程序