Postgres和Oracle与Hibernate的兼容性

本文详细介绍了在使用Hibernate时,如何处理Postgres和Oracle数据库之间的兼容性问题,包括BLOB、CLOB支持,布尔类型转换以及双表查询的解决方案,以实现JEE应用在不同数据库上的顺利运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在某些情况下,您的JEE应用程序需要支持Postgres和Oracle作为数据库。
Hibernate应该在这里完成工作,但是有些细节值得一提。
在为已经运行Oracle的应用程序启用Postgres时,我遇到了以下棘手的部分:

  • BLOBs支持,
  • CLOBs支持,
  • Oracle不知道Boolean类型(使用Integer ),并且
  • DUAL表。

这些是我必须使用的技巧,以使@Entity类在这两种方法上运行。

请注意,我已经将Postgres 9.3和Hibernate 4.2.1.SP1一起使用了。

BLOB支持

Postgres的问题在于它提供两种类型的BLOB存储:

  • bytea –表中存储的数据
  • oid –表仅保存存储在其他位置的数据的标识符

我猜在大多数情况下,您都可以像我一样使用bytea 。 据我所读,另一个用于一些大数据(千兆字节),因为它支持IO操作流。

好吧,听起来很高兴有这样的支持,但是在这种情况下使用Hibernate可能会带来很多问题(由于需要使用特定的批注),尤其是在您尝试与Oracle兼容的情况下。

要在此处查看问题,请参见StackOverflow:byte []的正确休眠注释

所有组合均在此处描述:

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

其中@Type(PBA)代表@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")@Type(BT)代表: @Type(type="org.hibernate.type.BinaryType")

这些会导致各种Postgres错误,例如:

错误:列“ foo”的类型为oid,但表达式的类型为bytea

要么

错误:列“ foo”的类型为bytea,但表达式的类型为oid

好吧,似乎有一个解决方案,它仍然包括对Hibernate库的修补(我在使用3.rd party库时看到的最后一个选择)。

Hibernate的专家们还引用了官方博客文章,主题是PostgreSQL和BLOB 。 仍然在博客文章中描述的解决方案似乎对我不起作用,并且基于这些评论,似乎对更多人无效。

BLOB已解决

好,现在是乐观的部分。

经过大量调试后,我最终得到了Entity定义,如下所示:

@Lob
private byte[] foo;

Oracle对此没有任何麻烦,而且我不得不以一种方式自定义Postgres方言:

public class PostgreSQLDialectCustom extends PostgreSQL82Dialect {

    @Override
    public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (sqlTypeDescriptor.getSqlType() == java.sql.Types.BLOB) {
      return BinaryTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }
}

而已! 很简单吧? 这适用于在Postgres中持久保存bytea类型的列(因为这适合我的用例)。

CLOB支持

错误配置中的错误如下所示:

org.postgresql.util.PSQLException: Bad value for type long : ...

因此,首先我找到了以下解决方案(在带有Hibernate 3.6的PostgreSQL上的String LOB上 ):

@Lob
@Type(type = "org.hibernate.type.TextType")
private String foo;

嗯,那行得通,但仅适用于Postgres。

然后有一个建议(关于StackOverflow:Postgres具有JDBC的Postgres UTF-8克隆 )可用于:

@Lob
@Type(type="org.hibernate.type.StringClobType")
private String foo;

那为我指明了正确的方向(有趣的是,这只是对一些答案的评论)。 它非常接近,但是在所有情况下都不适用于我,仍然导致测试出错。

CLOB已解决

重要的是org.hibernate.type.StringClobType中的@deprecation javadocs,这使我开始工作:

@Lob
@Type(type="org.hibernate.type.MaterializedClobType")
private String foo;

这适用于Postgres和Oracle,而无需任何进一步的黑客(在Hibernate方面)。

布尔型

Oracle不知道Boolean类型,而麻烦是Postgres知道。 由于也存在一些简单的SQL,我最终在Postgres中遇到错误:

错误:“ foo”列的类型为布尔值,但表达式的类型为整数

我决定在Postgres中启用从IntegerBoolean ,而不是固定所有普通的SQL位置(以论坛:自动从Integer到Boolean的转换 ):

update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');

请注意,您应该按用户权限运行SQL更新,以更新目录(可能不是您的postgres用户用于从应用程序进行数据库连接),正如我在Stackoverflow上了解到的:Postgres –拒绝更新pg_catalog.pg_cast的权限

双表

我遇到的Oracle中还有一个更具体的内容。 如果您使用普通的SQL,则在Oracle中提供了DUAL表(请参阅Wikipedia上的更多信息),这可能会对Postgres造成伤害。

解决方案仍然很简单。 在Postgres中创建一个视图,该视图将达到类似的目的。 可以这样创建:

create or replace view dual as select 1;

结论

好吧,应该是这样。 享受与跨数据库兼容的JEE应用程序。

参考:我们的JCG合作伙伴 Peter Butkovic在pb关于生活和IT博客的博客中 引用了 Postgres和Oracle与Hibernate的兼容性

翻译自: https://www.javacodegeeks.com/2014/03/postgres-and-oracle-compatibility-with-hibernate.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值