代码之家  ›  专栏  ›  技术社区  ›  Rakesh Goyal

休眠中的并发更新处理

  •  21
  • Rakesh Goyal  · 技术社区  · 14 年前

    目前,我们正在数据层中使用JDBC,并计划用Hibernate替换它。我刚开始休眠,不知道Hibernate是如何处理并发的。有人能给我解释一下,如果我们使用Spring进行事务管理,并发更新将如何处理:由Hibernate(在内存中,Hibernate的自动版本管理)处理,或者我必须将version列放在数据库中手动处理并发更新。

    4 回复  |  直到 7 年前
        1
  •  51
  •   Pascal Thivent    14 年前

    如果我们使用Spring进行事务管理,有人能解释一下Hibernate(在Hibernate的内存中自动版本管理)将如何处理并发更新,或者我必须在数据库中放置版本列来手动处理并发更新吗?

    不管您是否在使用Spring进行事务管理,这都不重要,而且在并发管理方面也不相关,这实际上是由Hibernate处理的。Hibernate可以使用两种策略来处理并发更新:乐观锁定和悲观锁定。

    乐观的

    使用乐观锁定时,将特殊属性(数字、时间戳)映射为 版本 (所以你实际上有一个专栏)。当检索实体和 包括 在更新和 递增的 通过Hibernate。

    为了说明这是如何工作的,让我们假设您按id=1和当前版本=1加载一个个人实体。保存之后,Hibernate将执行如下操作:

    update PERSON set ID=1, NAME='NAME 1', VERSION=2 where ID=1 and VERSION=1;
    

    所以,现在,假设有两个并发事务正在运行,每个事务都加载 相同的 实体(相同版本号)并更改名称。

    假设首先提交事务1,执行以下查询:

    更新person set id=1,name='name 1',version=2,其中id=1,version=1;
    

    它成功并且版本增加。

    然后提交事务2,执行以下查询:

    update PERSON set ID=1, NAME='NAME 2', VERSION=2 where ID=1 and VERSION=1;
    

    这个不会更新任何内容,因为WHERE子句与任何记录都不匹配。这就是您将得到一个乐观并发异常的地方。

    当您不维护连接、并发访问不频繁且扩展性非常好时,此策略是合适的。当然,只要映射一个版本属性,Hibernate就会为您透明地处理所有事情。

    悲观的

    当使用悲观锁定时,Hibernate会锁定一个记录以供您专用,直到您完成它为止(通常使用 SELECT ... FOR UPDATE )试图访问同一记录的任何其他并发事务都将被挂起,直到删除锁为止。这种策略以性能为代价提供了更好的可预测性,并且不会无限期地扩展。

    工具书类

        2
  •  1
  •   Chaitan Yadav    7 年前

    有一些JPA实现,比如ObjectDB,其中乐观锁是默认激活的,用户不需要在数据库表中维护版本变量,因为它是由ObjectDB内部处理的。乐观锁定在更新不频繁和锁定具有隐含成本的情况下是很好的,比如在电子商务中,锁定意味着业务损失。悲观锁是一种理想的锁,在这种情况下,并发性不需要太多需求,并且事务很快完成以释放资源。

        3
  •  0
  •   Bruno    14 年前

    有一些 documentation about sessions and transactions on the Hibernate community wiki . 它最终由底层RDBMS事务处理,但您需要注意加载或保存的对象的生命周期。

        4
  •  -2
  •   Lars Andren    14 年前

    Hibernate自己处理版本控制,一个健康的建议是不要篡改版本号。

    More on versioning in Hibernate

    A general but simple guide