目前我们在数据层使用JDBC并计划用hibernate替换它。我是Hibernate的新手,不知道hibernate如何处理并发。有人可以解释一下,如果我们使用spring进行事务管理,如何处理并发更新:通过hibernate(在hibernate的内存自动版本管理中)或者我必须将版本列放在数据库中以手动处理并发更新。 / p>
答案 0 :(得分:52)
如果我们使用spring进行事务管理,hibernate将如何处理并发更新(在hibernate的内存自动版本管理中),或者我必须将数据列放在数据库中以手动处理并发更新
无论您是否使用Spring进行事务管理并不重要,并且在并发管理方面无关紧要,这实际上是由Hibernate处理的。 Hibernate可以使用2种策略来处理并发更新:乐观锁定和悲观锁定。
使用乐观锁定时,您将特殊属性(数字,时间戳)映射为版本(因此您实际上有一个列)。当您在更新期间检索实体并在where子句中检索包含并且通过Hibernate 递增时,将读取此版本。
为了说明这是如何工作的,让我们假设您通过id = 1和当前版本= 1加载Person实体。保存之后,Hibernate将执行以下操作:
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
)。尝试访问同一记录的任何其他并发事务将被暂停,直到锁定被删除。该策略以性能价格提供更好的可预测性,并且无法无限扩展。
答案 1 :(得分:1)
有像objectDB这样的JPA实现,其中默认激活乐观锁定,用户不需要在数据库表中维护版本变量,因为它由objectDB内部处理。乐观锁定在不经常更新的情况下很好,并且锁定具有隐含成本,例如电子商务中锁定意味着业务损失。悲观锁定是不需要并发性很快并且事务快速完成以释放资源的理想选择。
答案 2 :(得分:0)
有一些documentation about sessions and transactions on the Hibernate community wiki。它最终由底层的RDBMS事务处理,但您需要注意加载或保存的对象的生命周期。
答案 3 :(得分:-2)