当前位置: 首页 > 面试题库 >

为byte []设置适当的休眠注释

江渊
2023-03-14
问题内容

我有一个使用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;
  }
}

当我们发现hibernate3.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 []属性的可移植方式是什么?
  • 在某些最新的hibernate版本中已解决此问题吗?

更新:
阅读此博客后,我终于弄清楚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,这是因为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对象和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/

问题答案:

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

这取决于您想要什么。JPA可以保留未注释的内容byte[]。根据JPA 2.0规范:

11.1.6基本注释

Basic注释是映射到数据库列的最简单的类型。所述Basic注释可以应用于以下任何类型的持久性或实例变量:Java原始,类型,原始类型的包装,
java.lang.Stringjava.math.BigIntegerjava.math.BigDecimal
java.util.Datejava.util.Calendarjava.sql.Date
java.sql.Timejava.sql.Timestampbyte[]
Byte[]
char[]Character[],枚举,以及任何其他类型的器具Serializable。如2.8节所述,Basic对于这些类型的持久字段和属性,注释的使用是可选的。如果未为此类字段或属性指定基本注释,则将应用基本注释的默认值。

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

但是,如果您希望将byte[]其存储在大对象中,则应使用@Lob。从规格:

11.1.24吊球注释

Lob注释指定持久性属性或字段应保持为一个大型对象到数据库支持的大对象类型。可移植应用程序Lob在映射到数据库Lob类型时应使用
注释。所述Lob注释可以与基本注释或与一起使用 ElementCollection的注释当元素集合值是基本类型。A
Lob可以是二进制或字符类型。Lob从持久字段或属性的类型推断出类型,并且,除了字符串和字符类型外,默认为Blob。

然后Hibernate会将其映射到BLOBPostgreSQL使用PostgreSQL处理的SQL oid

在某些最新的hibernate版本中已解决此问题吗?

好吧,问题是我不知道到底是什么问题。但是我至少可以说,自3.5.x分支中的3.5.0-Beta-2(已引入更改)以来,没有任何更改。

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

hibernate.jdbc.use_streams_for_binary=false

如果您想使用oidie byte[]@Lob(这是我的理解,因为VARBINARY这不是您想要的Oracle)。你有尝试过吗?

作为替代方案,HHH-4876建议使用不推荐使用的方法PrimitiveByteArrayBlobType来获得旧的行为(Hibernate
3.5之前的版本)。

参考文献

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

资源资源

  • http://opensource.atlassian.com/projects/hibernate/browse/HHH-4876
  • http://opensource.atlassian.com/projects/hibernate/browse/HHH-4617
  • http://relation.to/Bloggers/PostgreSQLAndBLOBs


 类似资料:
  • 问题内容: 当我尝试通过hibernate方式提交到SQL Server时出现JDBC错误 当IDENTITY_INSERT设置为OFF时,无法在表’Report’中为标识列插入显式值 我正在使用由包含以下内容的netbeans生成的映射: 在我看来,它应该正确地进行身份插入。 关于如何解决此问题的任何想法? 编辑: 一些文档链接,供后人, http://www.hibernate.org/hib

  • 问题内容: 在hibernate映射中,我设置了属性,这将获取父级的所有子级记录。 整个应用程序都在使用它。 这在我的应用程序的特定模块上造成了性能问题,我只想在其中获取父记录。 由于无法在其他许多地方使用该属性,因此我无法将其更改为。有没有办法来解决这个问题? 请让我知道是否需要更多信息。 问题答案: 这些在hibernate状态并不具有这种功能,因为它尊重您的习惯。因此,我建议解决您的需求的方

  • 问题内容: 我试图配置文件为我和应用。相关部分如下所示: 但是,如果我不将库直接包含到我的buildpath中,我会不断获取。我有什么问题吗,因为在构建项目时不会下载此依赖项? 问题答案: 尝试代替。 这将包括所有必需的依赖项。进行此更改后,请检查Maven依赖项层次结构。 顺便说一句,Maven Central中最新的hibernate版本是4.1.18。

  • 问题内容: 我有一个包含三个字段的表,例如a,b,c。我想添加一个约束,以确保如果a不为null,那么b和c也不为null。我已经使用以下SQL做到了 有没有一种方法可以使用hibernate注释@Check达到相同的效果? 我找不到带有该注释的有用示例,开发人员是否倾向于完全不使用它? 问题答案: 是的,可以在类级别使用,例如: (请注意,我使用@jarlh注释重写了您的情况。)该条款注释需要参

  • Hibernate需要提前知道 - 在哪里可以找到定义Java类与数据库表相关的映射信息。 Hibernate还需要一组与数据库和其他相关参数相关的配置设置。 所有这些信息通常作为标准的Java属性文件hibernate.properties ,或者作为名为hibernate.cfg.xml的XML文件提供。 我将考虑XML格式的文件hibernate.cfg.xml来指定我的示例中所需的Hibe

  • 问题内容: 它为什么如此重要?根据XML映射的优势是什么?你能解释这些吗?谢谢。 问题答案: 它不是“强制性”中的重要内容。有优势和劣势的可能性是不同的。 优点: 编译时检查:如今在IDE中,用Java(而不是Xml)编写非常易于使用。启动应用程序(渐进式编译)时,没有发现 更多错别字 ,也没有什么值得记住的( 完成 )… 使用代码进行本地化(类级别):不必打开两个文件(java和xml)以获取完