Hibernate之事务控制

目录

事务

事务的四个特性(ACID)

  1)原子性(Atomicity)

  2)一致性(Consistency)

  3)隔离性(Isolation)

  4)持久性(Durability)

事务并发问题(脏读、不可重复读、虚读)

1)脏读

2)不可重复读

3)幻读/虚读

扫描二维码关注公众号,回复: 2716335 查看本文章

事务隔离级别

1)读未提交(Read Uncommitted,1级)

2)读已提交(Read Committed,2级)

3)可重复读(Repeatable Read,4级)

4)序列化/串行化(Serializable,8级)

数据库隔离级别

MySQL(默认Repeatable Read)

Oracle(默认Read Committed)

Hibernate事务控制

确保同一个Session对象

修改Hibernate主配置文件

HibernateUtil工具类修改


事务

在数据库中,一项事务(Transaction)是由一条或多条操作数据的SQL语句组成的一个不可分割的工作单元。当事务中的所有操作都正常完成时,整个事务才能被提交到数据库中,如果有一项操作没有完成,则整个事务会被回滚。

总结起来理解为:逻辑上的一组操作,组成这组操作的各个单元,要么一起成功,要么一起失败

  • 事务的四个特性(ACID)

  1)原子性(Atomicity)

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生 

  2)一致性(Consistency)

一个事务中,事务前后数据的完整性必须保持一致

  3)隔离性(Isolation)

多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离

  4)持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

  • 事务并发问题(脏读、不可重复读、虚读)

1)脏读

一个事务读取到了另一个事务尚未提交的数据 (别人修改数据----提交完事务----你去读取----别人回滚事务)

2)不可重复读

一个事务读到了另一个事务已经提交的update数据,导致在同一个事务中多次查询结果不一致(别人已提交完事务----你去读取----别人修改数据已提交事务----你再次读取两次结果不一致)

3)幻读/虚读

一个事务读到了另一个事务已经提交的insert数据,导致在同一个事务中多次查询结果不一致(你正准备删空某表的记录----别人在你准备删除时向数据库该表里插入了一条数据----你并不知道有人向这个表插入数据,删除完校验时发现该表竟然还有数据,仿佛产生幻觉)

  • 事务隔离级别

为了避免事务并发问题的发生,在标准的SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同

1)读未提交(Read Uncommitted,1级)

一个事务在执行过程中,既可以访问其他事务未提交的新插入的数据,又可以访问未提交的修改数据。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据,此隔离级别可防止丢失更新

2)读已提交(Read Committed,2级)

一个事务在执行过程中,既可以访问其他事务成功提交的新插入的数据,又可以访问成功修改的数据。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行,此隔离级别可以有效防止脏读

3)可重复读(Repeatable Read,4级)

一个事务在执行过程中,可以访问其他事务成功提交的新插入的数据,但不可以访问成功修改的数据。读取数据的事务将会禁止写事务,但允许读事务,写事务则禁止任何其他事务,此隔离级别可以有效防止不可重复读和脏读

4)序列化/串行化(Serializable,8级)

提供严格的事务隔离,它要求事务系列化执行,事务只能一个接着一个地执行,不能并发执行,此隔离级别可有效防止幻读、不可重复读和脏读

  • 数据库隔离级别

在使用数据库时候,隔离级别越高,安全性越高,性能越低,在实际开发中,不会选择最高或最低隔离级别,一般选择默认的隔离级别

MySQL(默认Repeatable Read)

Read Uncommitted、Read Committed、Repeatable Read、Serializable

Oracle(默认Read Committed)

Read Uncommitted、Read Committed、Serializable

Hibernate事务控制

在Hibernate中,可以通过代码来操作管理实务,如通过以下代码开启一个事务:

          Transaction trans = session.beginTransaction();  //开启一个事务

 持久化操作后,通过以下代码提交事务:

trans.commit();   //提交事务

 如果出现异常,可以通过如下代码回滚事务:

trans.rollback();  //回滚事务

除了在代码中对事务开启,提交和回滚操作外,还可以在Hibernate的主配置文件中对事务进行配置,设置事务的隔离级别,通过<session-factory>标签元素在hibernate.cfg.xml文件中进行设置

<property name="hibernate.connection.isolation">4</property>  //设置事务的隔离级别

  • 确保同一个Session对象

在Service中开启事务时使用Session对象和DAO层中多个事务操作需要使用同一个Session对象,我们可以使用ThreadLocal将Service层获取的Session绑定到当前线程中,然后在DAO层中获取时,都从当前线程中获取

Hibernate的内部已经帮助我们解决了这个问题,我们主要完成相关配置即可

修改Hibernate主配置文件

在Hibernate的配置文件中,Hibernate.current_session_context_class属性用于指定Session管理方式,可选值包括:

1)thread     :Session对象的生命周期与本地线程绑定

2)jta           :Session对象的生命周期与JTA事务绑定

3)managed:Hibernate委托程序来管理Session对象的生命周期

<!-- 配置session绑定本地线程 -->
           <property name="hibernate.current_session_context_class">thread</property>

HibernateUtil工具类修改

Hibernate提供sessionFactory.getCurrentSession()创建一个session和ThreadLocal绑定方法

//获取当前线程绑定的会话

public static Session getCurrentSession(){

          return sessionFactory.getCurrentSession();

}

 注意:Hibernate中提供的这个与线程绑定的session不用关闭,当线程执行结束后,会自动关闭

猜你喜欢

转载自blog.csdn.net/mmake1994/article/details/81513473