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

网友投稿 228 2023-03-29


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

四种隔离机制不要忘记:(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中配置:

测试:

@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实现悲cztaDrr观锁和乐观锁代码介绍的全部内容,希望对大家学习hibernate有所帮助。有什么问题可以随时留言,会及时回复大家。感谢大家对本站的支持。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Struts2 OGNL表达式实例详解
下一篇:Mybatis 中的<![CDATA[ ]]>浅析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~