3

我正在使用 spring mvc 3.0 和休眠。我的情况是,我有库存,用户可以在其中添加和删除项目。例如,总量=50。现在,一次有两个用户想要更新库存,比如 A 删除了 2 件商品,B 删除了 4 件商品。所以,总数量 = 44。现在,当两个用户都尝试同时更新库存时,我该怎么做?? 如果不维护事务,那么它将是 50-2=48,然后是 50-4=46。

4

2 回答 2

2

使用版本属性来确保正确的语义。这是 Hibernate 参考指南的整个部分的主题:“乐观并发控制”

于 2012-05-01T05:34:11.530 回答
-1

您可以将乐观锁定与版本控制一起使用。将属性或属性添加到持久类映射后,就会启用带有版本控制的乐观锁定。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 仍然可以执行自动版本控制,但仅限于在同一持久性上下文(即同一 Session)中检索和修改的对象。这种版本控制的替代实现在检索对象时(或最后一次刷新持久性上下文)检查当前数据库状态与持久性属性的未修改值。您可以通过在类映射上设置乐观锁定属性来启用此功能:

<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》一书以了解更多详细信息。(推荐的)

编辑:瑞恩是对的。我纠正我的答案。

于 2012-05-01T11:52:44.407 回答