Hibernate悲观锁和乐观锁

Hibernate悲观锁和乐观锁

Hibernate加锁模式有如下五种,

1、LockMode.NONE,无锁模式

2、LockMode.WRITE ,Hibernate在insert和update的时候会自动使用这种锁

3、LockMode.READ,Hibernate在读取记录的时候会使用这种锁

以上三种锁是Hibernate内部使用的锁

4、LockMode.UPGRADE,这个锁是利用数据库的for update语句来实现,也是悲观锁的实现方式之一

5、LockMode.UPGRADE_NOWAIT,这个锁是针对于Oracle数据库,类似于第四种

 

悲观锁

所谓的悲观锁,就是在操作事务,总会认为会有其他事务操作同一数据,故不管有没有事务操作,他都对数据加锁。

Hibernate实现悲观锁方式如下:

代码如下:

                  String hql = "FROM User user where id=1";
  		Query query = session.createQuery(hql);
  		query.setLockMode("user", LockMode.UPGRADE);
 

日志输出如下:

Hibernate: select user0_.id as id0_, user0_.user_name as user2_0_, user0_.password as password0_, user0_.real_name as real4_0_ from test.user user0_ where user0_.id=1 for update


可以看到Hibernate使用了for update。

乐观锁

所谓的乐观锁,就是在操作事务的时候,总会认为就一个事务在操作,故对数据不加锁。

Hibernate实现乐观锁方式两种,

1、版本控制

2、时间戳控制

版本控制

版本控制即是Hibernate在操作数据的时候,会加上对应的version,当然了数据库表中需要有对应的字段,Hibernate会自动维护这个字段

如:

update user set user_name='test' where userId = 1 and version =0


乐观锁解决了不可重复读和第二类更新的问题

例子如下:

首先看配置文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.yindejin.vo.User" table="user" catalog="test">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="identity" />
        </id>
        <!-- version必须跟在id后面 -->
        <version name="version" type="java.lang.Integer">
        	<column name="version"></column>
        </version>
        <property name="userName" type="java.lang.String">
            <column name="user_name" length="200" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="password" length="200" />
        </property>
        <property name="realName" type="java.lang.String">
            <column name="real_name" length="200" />
        </property>
        
    </class>
</hibernate-mapping>


测试代码如下:

Configuration configuration = new Configuration().configure();
		Session session = configuration.buildSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		User user = new User();
		user.setUserName("test");
		user.setPassword("123456");
		session.save(user);
		user.setUserName("zhangsan");
		transaction.commit();
		session.close();


输出的日志如下:

Hibernate: insert into test.user (version, user_name, password, real_name) values (?, ?, ?, ?)
Hibernate: update test.user set version=?, user_name=?, password=?, real_name=? where id=? and version=?


可以看到Hibernate帮助我们自动管理了version。

时间戳控制

时间戳控制类似于version,也是添加一个字段,Hibernate替我们自动管理这个字段。

但是这种方式有一个很大问题,比如使用了F5的应用服务,服务被部署在多台服务器上,Hibernate在获取事件的时候,就会因为各个服务器上的时间不一致导致并发问题,所以并不推荐这种方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值