Hibernate使用hibernate.jdbc.batch_versioned_data保存过时数据
环境
Hibernate 4.2
ojdbc6 – Oracle 11.2.0.3.0 JDBC 4.0
Oracle数据库11g
问题
我们遵循了许多建议来配置我们的Hibernate批处理方式如下:
100 true true true
我们检查了日志,并且看到生成的SQL语句已经批处理。 但是,如果两个事务同时修改相同的版本化实体行,Hibernate将成功提交它们,导致最后提交的事务中的冲突更新丢失(非冲突数据保存在两个事务中,因此最后一个事务离开数据库处于不一致的状态)。
令人惊讶的是,关于这种行为的文档很少。 Hibernate官方文档说:
hibernate.jdbc.batch_versioned_data
如果JDBC驱动程序从executeBatch()返回正确的行计数,请将此属性设置为true。 打开此选项通常是安全的。 然后,Hibernate将使用批量DML来自动生成版本化数据。 默认为false。
通常安全 ? 在注意到整个版本控制被破坏之前,我们几乎将其发送到生产环境。
我们在五年前发布了一篇描述这种奇怪现象的博客 。 很明显,Hibernate很长一段时间没有做过任何事情。
Hibernate有这样的行为吗? 它从jdbc驱动程序获取更新行的计数未知的信息,为什么它不会抛出exception来指示它,而是留下版本检查已成功通过的印象?
oracle驱动程序应返回正确的行计数。 如果不是这样,我会感到惊讶。 您是否能够确认驱动程序的结果是否正确? 您可以打开Hibernate日志记录来检查这一点。
要检查的事情:
-
记录发送到数据库的实际SQL,并检查where子句中是否提到了version列。 不确定Hibernate日志记录是否通过批处理来记录SQL,您可能不得不采用不同的方式来记录SQL(例如,p6spy)
-
如果在并发更新期间正确返回行计数,则应用程序正常工作。 通过检查版本列的值是否已更新得到更正来确认。
更新根据以下链接,此问题已出现在Oracle驱动程序中,直到11g并在12c版本中修复
https://hibernate.atlassian.net/browse/HHH-3360
对于以前的Oracle版本,有一些应该有用的附加信息,即提供自定义解决方案。
其他资源: https : //hibernate.atlassian.net/browse/HHH-5070
- 使用hibernate与数据库连接时出错
- 创建自定义Hibernate UserType – isMutable()是什么意思?
- Hql,如何在具有一对多关系的表之间编写连接查询?
- 如何使用JPA / Hibernate选择DDL主键约束名称
- 为什么在添加元素以设置映射多对多时,hibernate从连接表中删除行?
- 如何使用Spring 4.0.6全局设置FlushMode for Hibernate 4.3.5.Final?
- 我需要这个错误的帮助:java.lang.NoSuchMethodError
- Spring boot + Hibernate
- Hibernate:在存储其更改时evict()一个持久对象