1. 云栖社区>
  2. 博客列表>
  3. 正文

【hibernate框架】使用hibernate实现悲观锁和乐观锁

光仔december 2015-03-10 15:48:00 浏览509 评论0

摘要: 四种隔离机制不要忘记:(1,2,4,8) 1.read-uncommitted:能够去读那些没有提交的数据(允许脏读的存在) 2.read-committed:不会出现脏读,因为只有另一个事务提交才会读取来 结果,但仍然会出现不可重复读和幻读现象。

四种隔离机制不要忘记:(1,2,4,8)
1.read-uncommitted:能够去读那些没有提交的数据(允许脏读的存在)
2.read-committed:不会出现脏读,因为只有另一个事务提交才会读取来
结果,但仍然会出现不可重复读和幻读现象。
4.repeatable read:MySQL默认。可重复读,读数据读出来之后给它加把锁,
其他人先别更新,等我用完了你再更新。你的事务没完,其他事务就不可能改这条记录。
8.serializable:序列化,最高级别。一个一个来,不去并发。效率最低。

hibernate的隔离机制
i.hibernate.connection.isolation=2

ii.用悲观锁解决:repeatable read的问题(依赖于数据库的锁)
a)LockMode.None 无锁的机制,Transaction结束时,切换到此模式
b)LockMode.read 在查询的时候 hibernate会自动获取锁
c)LockMode.write insert update hibernate会自动获取锁
d)以上3中锁的模式,是hibernate内部使用的
e)LockMode.UPGRADE_NOWAIT ORACLE支持的锁的方式

例子:
Account.java:
package com.bjsxt.hibernate;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;


@Entity
public class Account {
private int id;
private int balance; //BigDecimal
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}


}


hibernate.cfg.xml中配置:
<mapping class="com.bjsxt.hibernate.Account"/>

测试:
@Test
public void testSave() {
Session session = sf.openSession();
session.beginTransaction();

Account a = new Account();
a.setBalance(100);
session.save(a);

session.getTransaction().commit();
session.close();
}

@Test
public void testOperation1() {
Session session = sf.openSession();
session.beginTransaction();

Account a = (Account)session.load(Account.class, 1);
int balance = a.getBalance();
//do some caculations
balance = balance - 10;
//在保存时很有可能会把在同一时期修改的给覆盖掉
//这个时候上一把"锁"就可以避免这个问题
a.setBalance(balance);
session.getTransaction().commit();
session.close();
}


//下面这个就是对上面那个例子做的修改
@Test
public void testPessimisticLock() {
Session session = sf.openSession();
session.beginTransaction();

//给它加把锁,加锁的机制上面已经提到了
Account a = (Account)session.load(Account.class, 1, LockMode.UPGRADE);
int balance = a.getBalance();
//do some caculation
balance = balance - 10;
a.setBalance(balance);
session.getTransaction().commit();
session.close();
}
这是依赖于数据库的锁的,也就是给数据库一个指令,要求数据库帮忙加锁。
——————————————————————————————————————
iii.Hibernate(JPA)乐观锁定(ReadCommitted)
这不是依赖数据库加锁的,是在程序中加锁的。
举个例子:一个数据需要隔离机制(不能重复读),这个时候在更新的字段上加"版本号"(version字段),一旦有人给它update一下,这个值就加1(version+1)。
那么这种机制是如何产生隔离能力的呢?
原因是事务A读取字段的同时,事务B紧接着也读取这个字段,而且改了它,此时version变成1了。这个时候事务A就会检查字段是否被改变了,如果被改变它也做相应的改变,没有改变就不改。


乐观锁的实现:(@Version)
Account.java:
package com.bjsxt.hibernate;


import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Version;


@Entity
public class Account {
private int id;
private int balance;
private int version;


@Version//加了这个注解就说明这个是专门用来做版本标注的
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}


}


测试:
     
   @Test
public void testSave() {
Session session = sf.openSession();
session.beginTransaction();


Account a = new Account();
a.setBalance(100);
session.save(a);


session.getTransaction().commit();
session.close();
}


@Test
public void testOptimisticLock() {
Session session = sf.openSession();


Session session2 = sf.openSession();


session.beginTransaction();
Account a1 = (Account) session.load(Account.class, 1);

session2.beginTransaction();
Account a2 = (Account) session2.load(Account.class, 1);

a1.setBalance(900);
a2.setBalance(1100);


//第一个session一旦提交,version就会+1
session.getTransaction().commit();
System.out.println(a1.getVersion());


//第二个session提交的时候,一看version不一样就会报错
//出了错误做个记录,下次再提交(也可以用其他方法)
                session2.getTransaction().commit();
System.out.println(a2.getVersion());


session.close();
session2.close();
}

——————————————————————————————————————


悲观乐观的区别:悲观锁认为一定会受到影响,我加锁谁也别想动。

乐观锁,没出事就好,出了事我再想办法解决。

转载请注明出处:http://blog.csdn.net/acmman/article/details/44176281

版权声明:本文内容由互联网用户自发贡献,版权归作者所有,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:yqgroup@service.aliyun.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

用云栖社区APP,舒服~

【云栖快讯】中办国办印发《推进互联网协议第六版(IPv6)规模部署行动计划》加快推进基于 IPv6 的下一代互联网规模部署,计划指出2025年末中国 IPv6 规模要达到世界第一,阿里云也第一时间宣布了将全面提供IPv6服务,那么在全面部署 IPV6 前,你需要了解都在这儿  详情请点击

网友评论

关注
光仔december
目前致力于JavaEE(struts/hibe...
696篇文章|20关注
消息队列(Message Queue,简称MQ)是阿里云商用的专业消息中间件,是企业级互联网架构的核心产品,基于... 更多>

是一款提供了现场可编程门阵列(FPGA)的计算实例,基于阿里云弹性计算框架,用户可以几分钟内轻松创建FPGA实例... 更多>

充分利用阿里云现有资源管理和服务体系,引入中间件成熟的整套分布式计算框架,以应用为中心,帮助企业级客户轻松构建并... 更多>

为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本... 更多>
订阅广场全新上线

订阅广场全新上线