草庐IT

java - 字节 [] 的正确 hibernate 注释

coder 2023-04-27 原文

我有一个使用 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.5 breaks (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 中得到修复?

更新: 在阅读 this blog 之后,我终于弄清楚了 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 for bytea(不要问我为什么)和 postgresql 的自定义 Blob 类型用于 oids。另请注意,在 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 对象和 NOT MaterializedBlobType)。我从未真正成功地将 Blob 与 postgresql 一起使用,但我知道 bytea 只是像我所期望的那样工作。

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


2004 年的精彩引述: “总结一下我的胡言乱语,我想说我们应该等待 JDBC 驱动程序在更改 Hibernate 之前正确执行 LOB。”

引用资料:

最佳答案

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

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

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 处理。

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

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 会将其映射到 PostgreSQL 使用 oid 处理的 SQL BLOB .

Is this fixed in some recent version of hibernate?

嗯,问题是我不知道问题到底是什么。但我至少可以说,自 3.5.0-Beta-2 以来(在 3.5.x 分支中引入了更改),一切都没有改变。

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

hibernate.jdbc.use_streams_for_binary=false

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

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

引用文献

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

资源

关于java - 字节 [] 的正确 hibernate 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3677380/

有关java - 字节 [] 的正确 hibernate 注释的更多相关文章

  1. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  2. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  3. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  4. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

  5. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  6. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  7. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  8. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  9. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  10. Ruby - 如何将消息长度表示为 2 个二进制字节 - 2

    我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi

随机推荐