本文主要参考:http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#locking
基本知识:
在hibernate中可以选择的锁策略有两种:
-
乐观锁(Optimistic Locking)
-
悲观锁(Pessimistic Locking)
乐观锁假定多个事务可以在互不影响的情况下成功提交.因此, 事务不需要提前锁定当前事务所操作的数据资源.而是在事务提交之前,检测是否有其它事务也操作了当前事务所操作的数据. 如果发现了冲突,那么当前事务会回滚.
悲观锁假定当前事务会与其它事务冲突,因此需要提前对将要被操作的数据进行锁定,直到该应用不再使用该数据才会对数据进行解锁.
乐观锁
这种方法保证了一定的事务隔离,在read-often-write-sometimes情况下具有很好的可伸缩性,效果特别好.
当你的应用程序使用长事务或跨几个数据库的事务会话时,可以使用乐观锁. 你可以通过存储版本数据(version字段)来实现此类锁,如果相同的实体被两个会话更新,最后提交的更新会出现冲突,此时当前事务的修改不会覆盖其它事务提交的修改,当前事务会回滚.
详细请参考:http://docs.oracle.com/javaee/6/tutorial/doc/gkjhz.htm
使用方式:
这里这个字段可以使用任何实现了UserVersionType的类型
@Version
private long version;
文末我们给出完整demo.
悲观锁
通常,您只需要指定一个JDBC连接的隔离等级,然后让数据库处理锁问题。
锁模式和锁模式类型:
LockMode和LockModeType
要显示的设置上面的模式,可以通过一下几种方法:
Session.load(), Session.lock(), Session.setLockMode().
如果设置的模式不被底层数据库支持,Hibernate会使用一个合适的模式替换当前模式,而不会抛出异常.
示例:
实体类:
测试类:
hibernate创建的数据库为:
Hibernate:
create table OptimisticLockDemo (
id bigint not null,
name varchar(255),
version bigint not null,
primary key (id)
)
测试输出为:
main事务开始
Thread-1 事务开始
Hibernate:
select
optimistic0_.id as id1_5_0_,
optimistic0_.name as name2_5_0_,
optimistic0_.version as version3_5_0_
from
OptimisticLockDemo optimistic0_
where
optimistic0_.id=?
Thread-1事务被回滚
java.lang.NullPointerException
at OptimisticLockDemoTest$UpdateThread.run(OptimisticLockDemoTest.java:78)
Hibernate:
insert
into
OptimisticLockDemo
(name, version, id)
values
(?, ?, ?)
Hibernate:
update
OptimisticLockDemo
set
name=?,
version=?
where
id=?
and version=?
main事务提交成功
本文为头条号作者发布,不代表今日头条立场。