乐观的锁定和可扩展性

问题描述

我想知道optimistic locking mechanism在Hibernate中的用途是什么。所以,我在这里读过

https://vladmihalcea.com/preventing-lost-updates-in-long-conversations/关于这种情况:

1. Alice requests a certain product for being displayed
2. The product is fetched from the database and returned to the browser
3. Alice requests a product modification
4. The product must be updated and saved to the database

而且,在这种情况下使用乐观锁定确实是合理的。

但是,在持久性上下文中跟踪/保留了托管或分离的实体。持久性上下文仅限于存储过程。这是否意味着最多有一个服务实例可以使用它?

解决方法

乐观锁定的基本假设是您不会并行编辑同一条记录。这意味着我们不执行任何显式锁定或同步。我们加载数据,然后执行写操作。如果另一个事务已写入同一记录,则写入操作将失败。但是,它与服务实例的数量无关。实际上,使用乐观锁定和任意数量的服务实例,应用程序就有可能正常运行。

请考虑以下示例。拥有实体后,您将拥有一个用@Version注释的属性,如下所示...

@Entity
@Table(name="test_entity")
    public class TestEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id",nullable = false,unique = true)
    private Long id;
    @Column(name = "value",nullable = true)
    private String value;
    @Version
    @Column(nullable = false)
    private Integer version;

    ... getters & setters

}

然后输入代码:

session.saveOrUpdate(testEntity);
session.flush();

将生成以下查询...

update
    test_entity 
set
    value=?,version=? 
where
    id=? 
    and version=?

如果在同一服务实例或单独的实例中通过并行事务更改了版本,则hibernate将注意该更新不会影响数据库中的任何行,因为ID匹配,但是版本已更改通过另一笔交易。

在任何情况下(session.update(...)方法影响0行),hibernate都会抛出运行时异常以指示乐观锁已失败-OptimisticLockException。这意味着主要考虑因素是您是否认为您的用户将同时更新同一记录。

但是,如果您正在使用二级缓存,并且希望将其与开放式锁定结合使用,则需要确保您使用的是正确配置的分布式缓存。否则,二级缓存意味着您将从二级缓存(而不是从持久性上下文)而不是从数据库加载实例。在没有分布式缓存的情况下,您的二级缓存当然不会知道其他服务实例会更新记录,从而导致版本增加。然后,当您更新数据库中的记录(使用上面的查询)时,您更新了0条记录并获得了OptimisticLockException。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...