hibernate mysql锁机制_Hibernate事务隔离机制(乐观锁-悲观锁)

事务隔离机制

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-uncommited

2、read-commited

3、repeatable-read

4、serializable

a)  只要数据库支持事务,就不会出现read-uncommited情况

b) read-uncommited会出现dirty-read,phantom read,non-repeatable-read问题

c) sead-commited不会出现dirty-read,但仍会出现non-repeatable-read,phantom read

d) repeatable-read

e) 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;

@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;

}

}

(2)HibernateUtil.java,用于获取SessionFactory

package 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;

@BeforeClass

public static void beforeClass() {

sf = HibernateUtil.getSessionFactory();

}

@AfterClass

public static void afterClass() {

sf.close();

}

@Test

public void testSchemaExport() {

new SchemaExport(new Configuration().configure()).create(false, true);

}

@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进行操作,将会导致banlance取值被此session覆盖

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 caculations

balance = 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.java

package com.zgy.hibernate.model;

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;

}

}

(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;

@BeforeClass

public static void beforeClass() {

sf = HibernateUtil.getSessionFactory();

}

@AfterClass

public static void afterClass() {

sf.close();

}

@Test

public void testSchemaExport() {

new SchemaExport(new Configuration().configure()).create(false, true);

}

@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.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 的详细介绍:请点这里

Hibernate 的下载地址:请点这里

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值