环境
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驱动程序获取更新行的计数未知的信息,为什么它不会抛出异常来指示它,而是留下版本检查已成功通过的印象?
答案 0 :(得分:4)
oracle驱动程序应该返回正确的行数。如果不是这样,我会感到惊讶。您是否能够确认驱动程序的结果是否正确? 您可以打开Hibernate日志记录来检查它。
要检查的事情:
记录发送给DB的实际SQL,并检查where子句中是否提到了version列。不确定Hibernate日志记录是否通过批处理记录了SQL,您可能不得不采用不同的方式来记录SQL(例如,p6spy)
如果在并发更新期间正确返回行计数,则应用程序正常工作。通过检查版本列的值是否已更新更正来确认。
<强>更新强> 根据以下链接,此问题已出现在Oracle驱动程序中,直到11g并在版本12c中修复
https://hibernate.atlassian.net/browse/HHH-3360
对于以前的Oracle版本,有一些额外的信息应该是有用的,即提供自定义解决方案。