hibernate事务mysql_3.2 Hibernate的事务控制

1. 一级缓存

前面学习了一级缓存的主要两个作用:

提高效率手段1:提高查询效率

提高效率手段2:减少不必要的修改语句发送

现在开始了解一下Hibernate的事务控制。Hibernate是对JDBC的轻量级封装,其主要功能是操作数据库。在操作数据库过程中,经常会遇到事务处理的问题,那么我们接下来就介绍hibernate中的事务管理。

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

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

事务的四个特性:事务有很严格的定义,需要同时满足四个特性,即原子性、一致性、隔离性、持久性。这四个特性通常称之为ACID特性,具体如下:

原子性(Atomic):表示该事务中所做的操作捆绑成一个不可分割的单元,即对事务所进行的数据修改等操作,要么全部执行,要么全部不执行。

一致性(Consistency):表示事务完成时,必须使所有的数据都保持一致状态。

隔离性(Isolation):指一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务时隔离的,并发执行的各个事务之间不能互相干扰。

持久性(Durability):持久性也叫永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。提交后的其他操作或故障不会对其有任何影响。

事务的并发问题:在实际应用过程中,数据库是要被多个用户所共同访问的。在多个事务同时使用相同的数据时,可能会发生并发的问题,具体如下:

1).脏读:一个事务读取到另一个事务未提交的数据。

2).不可重复读:一个事务读到了另一个事务已经提交的update的数据,导致在同一个事务中的多次查询结果不一致。

2).虚读/幻读:一个事务读到了另一个事务已经提交的insert的数据,导致在同一个事务中的多次查询结果不一致。

事务的隔离级别

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

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

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

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

4. 序列化/串行化(Serializable, 8级):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。此隔离级别可有效的防止脏读、不可重复读和幻读。

READ_UNCOMMITTED: 允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读;

READ_COMMITTED: 允许在并发事务已经提交后读取。可防止脏读,但幻读和不可重复读仍可发生;

REPEATABLE_READ: 对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。

SERIALIZABLE:完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

事务的隔离级别,是由数据库提供的,并不是所有数据库都支持四种隔离级别:

Mysql:READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE(默认REPEATABLE_READ)

Oracle: READ_UNCOMMITTED、READ_COMMITTED、SERIALIZABLE(默认 READ_COMMITTED)

在使用数据库时候,隔离级别越高,安全性越高,性能越低。

实际开发中,不会选择最高或者最低隔离级别,选择READ_COMMITTED(oracle默认)、REPEATABLE_READ(mysql默认)

2 Hibernate事务管理

在Hibernate中,可以通过代码来操作管理事务,如通过

“Transaction tx=session.beginTransactiong();”

开启一个事务,持久化操作后,通过"tx.commit();" 提交事务;如果事务出现异常,又通过“tx.rollback();"操作来撤销事务(事务回滚)。

除了在代码中对事务开启,提交和回滚操作外,还可以在hibernate的配置文件中对事务进行配置。配置文件中,可以设置事务的隔离级别。其具体的配置方法是在hibernate.cfg.xml文件中的

标签元素中进行的。配置方法如下所示。

4

到这里我们已经设置了事务的隔离级别,那么我们在真正进行事务管理的时候,需要考虑事务的应用场景,也就是说我们的事务控制不应该是在DAO层实现的,应该在Service层实现,并且在Service中调用多个DAO实现一个业务逻辑的操作。具体操作如下显示:

de72f2d3698ed5ef2709cf1b692a521f.png

其实最主要的是如何保证在Service中开启的事务时使用的Session对象和DAO中多个操作使用的是同一个Session对象。

其实有两种办法可以实现:

1. 可以在业务层获取到Session,并将Session作为参数传递给DAO。

2. 可以使用ThreadLocal将业务层获取的Session绑定到当前线程中,然后再DAO中获取Session的时候,都从当前线程中获取。

其实使用第二种方式肯定是最优方案,那么具体的实现已经不用我们来完成了,hibernate的内部已经将这个事情做完了。我们只需要完成一段配置即可。

Hibernate5中自身提供了三种管理Session对象的方法

Session对象的生命周期与本地线程绑定

Session对象的生命周期与JTA事务绑定

Hibernate委托程序管理Session对象的生命周期

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

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

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

3. managed:hibernate委托程序来管理Session对象的生命周期。

在hibernate.cfg.xml中进行如下配置:

thread

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

在HibernateUtils工具类中更改getCurrentSession方法:

public static Session getCurrentSession() {

return sessionFactory.getCurrentSession();

}

而且Hibernate中提供的这个与线程绑定的session可以不用关闭,当线程执行结束后,就会自动关闭了。

所以最终的配置文件如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 <?xml version="1.0" encoding="UTF-8"?>

2

3

4

5 com.mysql.jdbc.Driver

6 jdbc:mysql:///day24_db

7 root

8 toor

9 org.hibernate.dialect.MySQLDialect

10 true

11 true

12 update

13

24

25

26 4

27

28 thread

29

30

31

hibernate.cfg.xml

最终的工具类如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagecn.eagle.utils;2

3 importorg.hibernate.Session;4 importorg.hibernate.SessionFactory;5 importorg.hibernate.cfg.Configuration;6

7 public classHibernateUtils {8

9 private static finalConfiguration configuration;10 private static finalSessionFactory sessionFactory;11

12 static{13 configuration = newConfiguration().configure();14 sessionFactory =configuration.buildSessionFactory();15 }16

17 public staticSession getCurrentSession() {18 returnsessionFactory.getCurrentSession();19 }20 }

Customer.hbm.xml

到这里我们已经对Hibernate的事务管理有了基本的了解,但是之前我们所做的CRUD的操作其实还没有查询多条记录。那如果我们需要查询多条记录要如何完成呢,我们接下去学习一下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值