Hibernate,Postgresql:列“x”的类型为oid,但表达式的类型为byte。

19

在切换不同的数据库时,我遇到了一个关于包含大对象(BLOB)的Hibernate映射的奇怪问题。

@Lob
private byte[] binaryData;

以上字段在 MySQL 和 Oracle 中创建一个字节数组字段,但在 PostreSQL 中它会创建一个 oid 类型的字段。

现在,当我尝试访问该字段时,它在其他数据库中正常工作,但在 PostgreSQL 中会出现以下错误:

Column "binaryData" is of type oid but expression is of type bytea.

我试图简单地删除“@Lob”注释,这将解决PostgreSQL的问题,但是在没有此注释的情况下,Hibernate会在MySQL中创建一个类型为“tinyblob”的字段,在大多数情况下太小了。而且,由于我们希望在不止一个环境中使用该项目,因此具有两个不同的映射切换很麻烦。

是否有任何注释可以强制PostgreSQL对使用@Lob注释的字段使用bytea而不是oid?或者是否有可能省略@Lob并放置其他内容以强制MySQL使用更大的数据类型来分配它,就像使用@Lob一样?

我甚至可以想象有这样的解决方案

if (field is of type oid)
  store it as oid
else if (field is of type bytea)
  store it as bytea
else
  // not storable

如果存在一种类似getter的方式,那么它也是一样的。

编辑:

以下声明可行。它将列分配为oid,但Hibernate使用它知道如何从这样的字段存储和检索数据。

@Lob
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
private byte[] binaryFile;
5个回答

13

该字段映射定义在org.hibernate.dialect.PostgreSQLDialect中,可以通过继承它并在使用postgres运行时配置应用程序以使用修改后的方言来更改。

子类中的相关咒语可能是将其放置为

    registerColumnType( Types.BLOB, "bytea" );
在你的构造函数中,在调用 super() 之后。

1
嗨 Don!谢谢您的回答。我试过了,它有效,但同时我找到了一个简单的解决方案并将其添加到问题中。 - Hons

4

Hibernate 6+, javaee 9+

  @Lob
  @JdbcTypeCode(Types.BINARY)
  private byte[] binaryData;

1
对我来说,这可能意味着将您的Postgres JDBC版本回退到9.3-1101.jdbc4。
  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>9.4-1200-jdbc41</version>
  </dependency>

工作得很好。比那更新的失败了...


1

0

PostgreSQL的大对象是oid类型,因为它们实际上是指向另一个表pg_largeobject_metadata中对象的引用。

JDBC接口将oid映射为java.sql.Types.DISTINCT

任何Hibernate方言都不知道这是Blob类型,但您可以提供自己的方言来将其视为等效的:

public static class PostgreSQLDialect extends PostgreSQL10Dialect {
    @Override
    public boolean equivalentTypes(int type1, int type2) {
        return super.equivalentTypes(type1, type2) ||
                (type1 == Types.BLOB && type2 == Types.DISTINCT) ||
                (type1 == Types.DISTINCT && type2 == Types.BLOB);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接