十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章将为大家详细讲解有关悲观锁与乐观锁怎么利用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实现就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。