Hibernate使用hibernate.jdbc.batch_versioned_data

时间:2015-05-29 00:36:37

标签: java oracle hibernate ojdbc

环境

Hibernate 4.2

ojdbc6 - Oracle 11.2.0.3.0 JDBC 4.0

Oracle Database 11g

问题

我们遵循了许多建议,以下列方式配置我们的Hibernate批处理:

<property name="hibernate.jdbc.batch_size">100</property>
<property name="hibernate.order_inserts">true</property>
<property name="hibernate.order_updates">true</property>
<property name="hibernate.jdbc.batch_versioned_data">true</property>

我们检查了日志,我们看到生成的SQL语句已经批处理。但是,如果两个事务同时修改相同的版本化实体行,Hibernate将成功提交它们,导致最后提交的事务中的冲突更新丢失(非冲突数据保存在两个事务中,因此最后一个事务离开数据库处于不一致的状态)。

令人惊讶的是,关于此行为的文档很少。 Hibernate官方documentation说:

  

hibernate.jdbc.batch_versioned_data

     

如果你的话,请将此属性设置为true   JDBC驱动程序从executeBatch()返回正确的行计数。它是   打开此选项通常是安全的。然后Hibernate将使用批处理   DML用于自动版本化数据。默认为false。

通常是安全的?在注意到整个版本控制被破坏之前,我们几乎将其发送到生产中。

我们在五年前发布了一篇blog来描述这种古怪的东西;很明显,Hibernate很长一段时间没有做任何事情。

Hibernate有这样的行为吗?它从jdbc驱动程序获取更新行的计数未知的信息,为什么它不会抛出异常来指示它,而是留下版本检查已成功通过的印象?

1 个答案:

答案 0 :(得分:4)

oracle驱动程序应该返回正确的行数。如果不是这样,我会感到惊讶。您是否能够确认驱动程序的结果是否正确? 您可以打开Hibernate日志记录来检查它。

要检查的事情:

  1. 记录发送给DB的实际SQL,并检查where子句中是否提到了version列。不确定Hibernate日志记录是否通过批处理记录了SQL,您可能不得不采用不同的方式来记录SQL(例如,p6spy)

  2. 如果在并发更新期间正确返回行计数,则应用程序正常工作。通过检查版本列的值是否已更新更正来确认。

  3. <强>更新 根据以下链接,此问题已出现在Oracle驱动程序中,直到11g并在版本12c中修复

    https://hibernate.atlassian.net/browse/HHH-3360

    对于以前的Oracle版本,有一些额外的信息应该是有用的,即提供自定义解决方案。

    其他资源: https://hibernate.atlassian.net/browse/HHH-5070