事务隔离机制
1、事务:ACID
2、事务并发时可能出现的问题
a) 第一类丢失更新
| 时间 | 取款事务A | 存款事务B |
| T1 | 开始事务 | |
| T2 | | 开始事务 |
| T3 | 查询账户余额为1000元 | |
| T4 | | 查询账户余额为1000元 |
| T5 | | 汇入100元把余额改成1100元 |
| T6 | | 提交事务 |
| T7 | 取出100元把余额改成900元 | |
| T8 | 撤销事务 | |
| T9 | 余额恢复为1000元(丢失更新) | |
b) dirty read脏读(读了另一个事务没有提交的数据)
| 时间 | 取款事务A | 存款事务B |
| T1 | 开始事务 | |
| T2 | | 开始事务 |
| T3 | | 查询账户余额为1000元 |
| T4 | | 汇入100元把余额改成1100元 |
| T5 | 查询账户余额为1100元(读取脏数据) | |
| T6 | | 回滚 |
| T7 | 取款1100元 | |
| T8 | 事务提交失败 | |
c) non-repeatable-read不可重复读(同一个事务中,读取同一个数据,得到的值不同)
| 时间 | 取款事务A | 转账事务B |
| T1 | 事务开始 | |
| T2 | | 事务开始 |
| T3 | 查询账户余额为1000元 | |
| T4 | | 汇入100元把余额改成1100元 |
| T5 | | 提交事务 |
| T6 | 查询账户余额为1100元 | |
| T7 | 提交事务 | |
d)second lost update problems第二类丢失更新(不可重复读的特殊情况)
| 时间 | 转账事务A | 取款事务B |
| T1 | | 开始事务 |
| T2 | 开始事务 | |
| T3 | | 查询账户余额为1000元 |
| T4 | 查询账户余额为1000元 | |
| T5 | | 取出100元把余额改成900元 |
| T6 | | 提交事务 |
| T7 | 汇入100元 | |
| T8 | 提交事务 | |
| T9 | 把余额改成1100元(丢失更新) | |
e) phantom read 幻读(插入、删除问题导致取得的结果不同)
| 时间 | 查询学生事务A | 插入学生事务B |
| T1 | 开始事务 | |
| T2 | | 开始事务 |
| T3 | 查询学生为10人 | |
| T4 | | 插入一个新学生 |
| T5 | 查询学生为11人 | |
| T6 | | 提交事务 |
| T7 | 提交事务 | |
3、数据库的事务隔离机制
1、read-uncommited2、read-commited3、repeatable-read4、serializable a) 只要数据库支持事务,就不会出现read-uncommited情况 b) read-uncommited会出现dirty-read,phantom read,non-repeatable-read问题c) sead-commited不会出现dirty-read,但仍会出现non-repeatable-read,phantom readd) repeatable-reade) serializable解决一切问题
4、设定hibernate的事务隔离级别
1、为了考虑并发效率,设置Hibernte.connection.isolate=2(即使用的是read-commited)2、用悲观锁解决repeatable read问题(依赖于数据库的锁)A)相当于select ...for update 悲观锁:实验:(1)建立Account.java类package com.zgy.hibernate.model; import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id; @Entitypublic class Account {private int id;private int balance; //BigDecimal@Id@GeneratedValuepublic 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;} }(2)HibernateUtil.java,用于获取SessionFactorypackage com.zgy.hibernate.model; import org.hibernate.SessionFactory;import org.hibernate.boot.registry.StandardServiceRegistryBuilder;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry; public class HibernateUtil {static SessionFactory sessionFactory = buildSessionFactory(); private static SessionFactory buildSessionFactory() {Configuration configure = new Configuration().configure();ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configure.getProperties()).build();return sessionFactory = configure.buildSessionFactory(serviceRegistry);} public static SessionFactory getSessionFactory(){return sessionFactory;}}(3)测试类package com.zgy.hibernate.model; import org.hibernate.LockMode;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.tool.hbm2ddl.SchemaExport;import org.junit.AfterClass;import org.junit.BeforeClass;import org.junit.Test; public class HibernateLockTest {private static SessionFactory sf; @BeforeClasspublic static void beforeClass() {sf = HibernateUtil.getSessionFactory();}@AfterClasspublic static void afterClass() {sf.close();} @Testpublic void testSchemaExport() {new SchemaExport(new Configuration().configure()).create(false, true);} @Testpublic void testSave() {Session session = sf.openSession();session.beginTransaction(); Account a = new Account();a.setBalance(100);session.save(a); session.getTransaction().commit();session.close();} @Testpublic void testOperation1() {Session session = sf.openSession();session.beginTransaction(); Account a = (Account)session.load(Account.class, 1);int balance = a.getBalance();//do some caculations,此时如果别的事务在这个过程中对balance进行操作,将会导致banlance取值被此session覆盖balance = balance - 10;a.setBalance(balance);session.getTransaction().commit();session.close();} @Testpublic void testPessimisticlock() {Session session = sf.openSession();session.beginTransaction(); Account a = (Account)session.load(Account.class, 1,LockMode.UPGRADE);int balance = a.getBalance();//do some caculationsbalance = balance - 10;a.setBalance(balance);session.getTransaction().commit();session.close();}public static void main(String[] args) {beforeClass();}}(4)测试testPessimisticlock()方法,观察产生的SQL语句如下:Hibernate: select account0_.id as id1_0_0_, account0_.balance as balance2_0_0_ from Account account0_ where account0_.id=? for update Hibernate: update Account set balance=? where id=? 乐观锁:实验:(1)修改Account.javapackage com.zgy.hibernate.model; import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Version; @Entitypublic class Account {private int id;private int balance;private int version;@Versionpublic int getVersion() {return version;}public void setVersion(int version) {this.version = version; }@Id@GeneratedValuepublic 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;} } (2)测试:package com.zgy.hibernate.model; import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.hibernate.tool.hbm2ddl.SchemaExport;import org.junit.AfterClass;import org.junit.BeforeClass;import org.junit.Test; public class HibernateLockTest {private static SessionFactory sf; @BeforeClasspublic static void beforeClass() {sf = HibernateUtil.getSessionFactory();}@AfterClasspublic static void afterClass() {sf.close();} @Testpublic void testSchemaExport() {new SchemaExport(new Configuration().configure()).create(false, true);} @Testpublic void testSave() {Session session = sf.openSession();session.beginTransaction(); Account a = new Account();a.setBalance(100);session.save(a); session.getTransaction().commit();session.close();} @Testpublic 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.getTransaction().commit();System.out.println(a1.getVersion()); session2.getTransaction().commit();System.out.println(a2.getVersion()); session.close();session2.close();} public static void main(String[] args) {beforeClass();}}(3)观察结果: 程序出错,因为session2中的数据被修改或者删除,所以导致session2无法正常关闭。Hibernate整体理解 http://www.linuxidc.com/Linux/2014-07/104405.htmHibernate的映射机制 http://www.linuxidc.com/Linux/2014-12/110265.htm
Hibernate 的详细介绍:请点这里
Hibernate 的下载地址:请点这里
本文永久更新链接地址