休眠状态下的并发更新处理

2022-09-01 15:09:11

目前,我们正在数据层中使用JDBC,并计划将其替换为休眠。我是Hibernate的新手,不确定Hibernate如何处理并发。有人可以解释一下,如果我们使用spring进行事务管理,如何处理并发更新:通过休眠(在内存中自动版本管理hibernate),或者我必须将版本列放在数据库中以手动处理并发更新。


答案 1

有人可以解释一下,如果我们使用spring进行事务管理,如何通过休眠(在内存中自动版本管理休眠)来处理并发更新,或者我必须将版本列放在数据库中以手动处理并发更新。

无论你是否使用Spring进行事务管理并不重要,并且在并发管理方面也无关紧要,这实际上是由Hibernate处理的。休眠可以使用 2 种策略来处理并发更新:乐观锁定和悲观锁定。

乐观的

使用乐观锁定时,将特殊属性(数字,时间戳)映射为版本(因此您实际上有一列)。当您检索实体时,将读取此版本,并在更新期间将其包含在 where 子句中,并由 Hibernate 递增

为了说明其工作原理,让我们假设您按 id=1 加载 Person 实体,并使用当前版本=1 加载 Person 实体。保存后,休眠将执行如下操作:

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

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

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

update PERSON set ID=1, NAME='NAME 1', VERSION=2 where ID=1 and 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

有像objectDB这样的JPA实现,其中乐观锁定默认被激活,用户不需要在数据库表中维护版本变量,因为它由objectDB内部处理。在更新不频繁的地方,乐观锁定是好的,并且在锁定有隐性成本的地方,例如在电子商务中,锁定意味着业务损失。悲观锁定是理想的选择,其中对并发性的要求不高,并且事务快速完成以释放资源。


推荐