您可以使用带版本控制的乐观锁定。 只需将 或 属性添加到持久类映射中,即可启用带版本控制的乐观锁定。 在 XML 中,属性映射必须紧随标识符属性映射之后:
<class name="Item" table="ITEM">
<id .../>
<version name="version" access="field" column="OBJ_VERSION"/>
...
</class>
有了这个,当项目更新时,SQL 将会是:
update ITEM set INITIAL_PRICE='12.99', OBJ_VERSION=2
where ITEM_ID=123 and OBJ_VERSION=1
如果另一个并发工作单元更新并提交了相同的行,则OBJ_VERSION列不再包含值1,该行也不会被更新。Hibernate通过JDBC驱动程序返回的语句行数(在本例中为零)检查此语句的行数,并抛出StaleObjectStateException异常。
如果您没有版本或时间戳列,Hibernate仍然可以执行自动版本控制,但仅适用于在相同持久性上下文(即相同会话)中检索和修改的对象。版本控制的这种替代实现将当前数据库状态与检索对象时(或最后一次刷新持久性上下文时)的未修改持久属性的值进行比较。您可以通过设置类映射上的optimistic-lock属性来启用此功能:
<class name="Item" table="ITEM" optimistic-lock="all">
<id .../>
...
</class>
现在执行以下SQL来刷新Item实例的修改: update ITEM set ITEM_PRICE='12.99' where ITEM_ID=123 and ITEM_PRICE='9.99' and ITEM_DESCRIPTION="An Item" and ... and SELLER_ID=45
在这两种情况下,你需要重新启动第二个事务或合并更新,以解决StaleObjectStateException。这种情况应该很少见,否则,你需要重构以减少事务范围,使其更小、更快。
你可以参考CHRISTIAN BAUER和GAVIN KING的《Java Persistent with Hibernate》一书获取更多细节。(推荐)
编辑:Ryan是正确的。我更正了我的答案。