【问题标题】:Hibernate+Oracle+Clob: Content of attributes get switchedHibernate+Oracle+Clob:属性内容被切换
【发布时间】:2010-07-05 08:33:47
【问题描述】:

有没有人听说过这个错误:

我有一个 Java 5 应用程序,它使用 Hibernate 3.3.2 访问 Oracle 数据库 10g,JDBC 驱动程序是 Oracle 轻驱动程序版本 10.2.0.4.0(我认为是最新版本)。 数据库访问发生在通过 spring 的 AOP 工具管理的事务期间。 有一个数据库表映射到一个 Java 实体,映射是通过注解完成的。此实体中有两个属性是数据库中的 CLOB。它们根据 JPA 使用“Lob”进行注释,并且是 Java 字符串。一切正常,除非两个属性的值都超过 4000 个字符:提交后,值在数据库上被切换,即属性 A 包含属性 B 的值,反之亦然。

这不是玩笑!

Eclipse 调试器告诉我 Java 实体具有正确的值,直到事务关闭(我没有调试到 Spring 事务处理)。 如果两个 Clob 都使用 Hibernate 注释 'Type(type = "clob")' 进行注释,则不会发生此错误(在这种情况下,它们必须是 java.sql.Clob 类型而不是 String,当然)。

【问题讨论】:

    标签: oracle hibernate jpa clob


    【解决方案1】:

    我不能 100% 确定,但您能否尝试将连接属性 SetBigStringTryClob 设置为 true(请参阅 How To Handle CLOBs Easily in JDBC?)。

    如果您使用的是 Spring,则如下所示:

    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.connection.SetBigStringTryClob">true</prop>
      </props>
    </property>
    

    【讨论】:

    • 是的,谢谢,这应该可以修复 CLOB 属性中超过 32kB 的错误,但我确实尝试过,但无济于事。在 stackoverflow 和其他地方有几个关于单个 CLOB 属性和超过 4000 个字符或更多字符的问题的问题。我希望我都能找到它们 :-) 请注意,我的问题仅在至少两个属性超过 4000 个字符时才会出现。
    • @Tim TBH,这更像是在黑暗中拍摄。实际上,您的情况真的很奇怪(我想知道 正在交换值)并且在某处闻起来像一个讨厌的错误。将此问题添加到我的最爱中以关注此故事。
    • 我的猜测是 a) CLOB 值在包含超过 4000 个字符时需要特殊处理,并且 b) Hibernate 或 Oracle JDBC 驱动程序有一个错误,如果有多个值,则切换值需要这种额外的处理。但是我没有时间调试两者,而且我没有在 Hibernate 错误数据库中找到类似的错误。 (我不能简单地升级 Hibernate,因为该软件在生产中使用,并且更改整个 Hibernate 发行版需要对整个软件进行彻底的测试)。
    • @Tim a) 是的,这就是我建议尝试上述选项的原因 b) 我将运行一个简单的 JDBC 测试以查看 JDBC 驱动程序如何处理原始 JDBC 代码。如果你重现问题,那么你就会知道它在哪里:)
    【解决方案2】:

    同时我找到了解决问题的方法:SQL方言错误,有人将其设置为Oracle9而不是正确的版本,即:

    name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"

    设置正确的 SQL 方言可以解决问题 :-)

    【讨论】:

      【解决方案3】:

      我也有同样的问题。一张桌子上有两个 CLOB。在插入件上只设置了一个,一切都很好。在更新时,我设置了第二个,并在提交后交换了表上的值。两者都包含超过 4000 个字符。调试和bean上的值是正确的。 可悲的是,我的属性中已经有 org.hibernate.dialect.Oracle10gDialect。 (休眠版本4.2.2.Final)

      //更新 目前作为一种解决方法,我在 JPA 注释中将第一列设置为 updatable=false ,这样在通过休眠生成更新查询期间,现在只有一个 CLOB 列。我可以这样做,因为在这种特殊情况下我不需要在插入后更改值,但这不是一般的解决方案。

      【讨论】:

        【解决方案4】:

        唯一对我们有用的是使用 hql 查询进行更新。每个查询更新一个 CLOB(因此我们需要两个单独的查询):

        Query query = em.createQuery("update SomeTable as someTable set value = :value where id = :id");
        query.setParameter("value", value);
        query.setParameter("id", id);
        if (query.executeUpdate() != 1) {
            throw new Exception("Value update had no effect");
        }
        

        【讨论】:

          猜你喜欢
          • 2011-04-11
          • 1970-01-01
          • 2010-12-04
          • 1970-01-01
          • 2016-11-24
          • 2012-03-28
          • 2014-02-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多