当前,我们在数据层中使用JDBC,并计划用hibernate代替它。我是Hibernate的新手,不确定Hibernate如何处理并发。如果我们使用spring进行事务管理,有人可以解释一下我如何处理并发更新:通过hibernate(在内存中进行hibernate的自动版本管理),或者我必须将version列放入数据库中以手动处理并发更新。
无论你是否使用Spring进行事务管理都没有关系,并且在并发管理方面也没有关系,这实际上是由Hibernate处理的。Hibernate可以使用2种策略来处理并发更新:乐观锁定和悲观锁定。
Optimistic
使用开放式锁定时,你将特殊属性(数字,时间戳记)映射为版本(因此实际上有一个列)。检索实体时将读取此版本,并在更新过程中将其包含在where子句中并由Hibernate 递增。
为了说明这是如何工作的,我们假设你以id = 1且当前版本为1加载Person实体。保存后,Hibernate将执行以下操作:
update PERSON set ID=1, NAME='NAME 1', VERSION=2 where ID=1 and VERSION=1;
因此,现在,假设你正在运行两个并发事务,每个事务都加载相同的实体(相同的版本号)并更改名称。
假设首先提交事务#1,然后执行以下查询:
成功,版本增加。
然后提交事务#2,执行以下查询:
update PERSON set ID=1, NAME='NAME 2', VERSION=2 where ID=1 and VERSION=1;
此语句不会更新任何内容,因为where子句与任何记录都不匹配。在这里,你将获得乐观的并发异常。
当你不维护连接,并发访问不频繁且扩展性很好时,此策略是合适的。只要映射了版本属性,Hibernate就会为你透明地处理所有内容。
Pessimistic
使用pessimistic锁定时,Hibernate会锁定记录供你独占使用,直到你完成该记录为止(通常使用SELECT ... FOR UPDATE)。尝试访问同一记录的任何其他并发事务将被挂起,直到删除锁为止。这种策略以性能为代价提供了更好的可预测性,并且不会无限扩展。
SELECT ... FOR UPDATE