欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Hibernate实现悲观锁和乐观锁代码介绍

程序员文章站 2024-03-03 16:48:40
四种隔离机制不要忘记:(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(); 
} 

悲观乐观的区别:悲观锁认为一定会受到影响,我加锁谁也别想动。
乐观锁,没出事就好,出了事我再想办法解决。

总结

以上就是本文关于hibernate实现悲观锁和乐观锁代码介绍的全部内容,希望对大家学习hibernate有所帮助。有什么问题可以随时留言,小编会及时回复大家。感谢大家对本站的支持。