7

我们使用 Hibernate 作为 JPA 提供者,并且我们有一个带有标记为大对象字段的类

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

该列创建为

SOMESTRING            LONG()             

这与 PostgreSQL 和 MySQL 完美配合。持久化对象时使用 Oracle

entityManager.persist( object );

我们得到一个org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update例外。

删除@Type( type = "org.hibernate.type.TextType" )注释将解决 Oracle 的问题,但会引入 PostgreSQL 的编码问题,如使用 Hibernate/PostgreSQL 无法将欧洲符号存储到 LOB 字符串属性中所述

我想知道如何定义一个大文本字段,以便 out 程序在 PostgreSQL 和 Oracle 上都可以工作。纯 JPA 解决方案将是最佳解决方案,但特定于 Hibernate 的解决方案也可以。

编辑:

真正的例外:

java.sql.BatchUpdateException: ORA-22295: cannot bind more than 4000 bytes data to LOB and LONG columns in 1 statement

现在,我错过的异常解释了问题,实际上我坚持的对象比大字符串(至少一个长 DBID)还要多。

4

5 回答 5

4

这对我有用。像这样扩展 PostgreSQL81Dialect:

public class MyPostgreSQL81Dialect extends PostgreSQL81Dialect
{

  @Override
  public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode)
  {
    SqlTypeDescriptor descriptor;
    switch (sqlCode)
    {
      case Types.CLOB:
      {
        descriptor = LongVarcharTypeDescriptor.INSTANCE;
        break;
      }
      default:
      {
        descriptor = super.getSqlTypeDescriptorOverride(sqlCode);
        break;
      }
    }  
    return descriptor;
  }

}
于 2013-12-13T07:35:25.443 回答
3

学分应该去其他地方(给用户称为:@liecno),但基于(他的)评论之一:Postgres UTF-8 clob with JDBC,可以通过以下方式简单地实现与 Oracle 和 Postgres 的兼容性:

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

更新:

好的,经过一些测试,我找到了更新的解决方案,适用于我的所有场景。由于org.hibernate.type.StringClobType已弃用(hibernate 4.2.x),我去了它的替代品:org.hibernate.type.MaterializedClobType.

@Lob
@Type(type="org.hibernate.type.MaterializedClobType")
private String someString;
于 2014-02-10T10:05:59.400 回答
1

该错误意味着,Oracle 无法在一次更新中处理两列超过 4000 字节的列。在过去,Oracle 已经遇到过这个问题——我记得每个表只允许一个 LONG 列的版本。我想知道他们没有删除这个问题。(我不知道该表中是否真的有第二个 LONG 或 LOB 列,但我想会有一个。)

我认为删除@Type注释通常不能解决问题。在您的测试中,效果可能是只有不到 4000 个字节,但是对于其他数据,也可能会出现错误。

解决方案:我认为你已经将更新语句分成两个语句,就像我在这里画的那样(批量更新仍然是可能的):

for (many rows) {
  object.setFirstLongColumn(...);
  persist(object);
  session.flush();
  object.setSecondLongColumn(...);
  persist(object);
  session.flush();
}
commit();

session.flush()对于防止 Hibernate 更改可能干扰您的逻辑的数据库语句的顺序是必要的。

还有一件事:LONG在 Oracle 中已被弃用。如果你运气好,那么在数据库中用 LOB 替换 LONG 可以解决你的问题。

于 2012-10-30T10:15:14.053 回答
1

我遇到了类似的问题,唯一的方法是扩展/自定义 Oracle 方言。

于 2012-11-01T10:21:41.430 回答
1
@Lob
private String someString;

告诉 Hibernate 将其视为“物化 CLOB”。由于 @Lob 注释而导致的 CLOB,因为我们必须从 CLOB 定位器中提取字符串/字符而具体化。

当我在这里说 CLOB 时,我的意思是 java.sql.Types.CLOB。所以JDBC类型代码。然而,Hibernate 在这里有另一个层次的间接性:方言。方言能够定义类型代码如何映射到物理数据库类型(用于模式导出、转换调用等)以及如何对 PreparedStatement/ResultSet 执行绑定/提取操作。PostgreSQL 方言将 Types.CLOB 映射到物理“文本”数据类型;Oracle 方言将其映射到物理 CLOB 数据类型;MySQL 方言将其映射到物理“longtext”数据类型。

于 2012-11-01T14:45:23.263 回答