Hibernate是对JDBC的轻量级封装,其主要功能是操作数据库。在操作数据库过程中,经常会遇到事务处理的问题,接下来就来介绍Hibernate中的事务管理。

  在学习Hibernate中的事务处理之前,先来回顾一下什么是事务。

一、事务概述

1.1 什么是事务

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

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

1.2 事务的四个特性

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

  • 原子性(Atomic):表示该事务中所做的操作捆绑成一个不可分割的单元,即对事务所进行的数据修改等操作,要么全部执行,要么全部不执行。
  • 一致性(Consistency):表示事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(Isolation):指一个事务的执行不能被其它事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务时隔离的,并发执行的各个事务之间不能互相干扰。
  • 持久性(Durability):持久性也叫永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。提交后的其他操作或故障不会对其有任何影响。

1.3 事务的并发问题

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

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

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

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

1.4 事务的隔离级别

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

  • 读未提交(Read Uncommitted,1级): 一个事务在执行过程中,既可以访问其他事务提交的新插入的数据,又可以访问未提交的修改数据。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。此隔离级别可防止丢失更新。
  • 读已提交(Read committed, 2级): 一个事务在执行过程中,既可以访问其他事务成功提交的新插入的数据,又可以访问成功修改的数据。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。此隔离级别可有效防止脏读。
  • 可重复读(Repeatable Read, 4级): 一个事务在执行过程中,可以访问其他事务成功提交的新插入的数据,但不可以访问成功修改的数据。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。此隔离级别可有效的防止不可重复读和脏读。
  • 序列化/串行化(Serializable, 8级):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。此隔离级别可有效的防止脏读、不可重复读和幻读。

    

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

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

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

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

二、Hibernate的事务管理

  在Hibernate中,可以通过代码来操作管理事务,如通过“Transaction tx=session.beginTransactiong();”开启一个事务,持久化操作后,通过"tx.commit();" 提交事务;如果事务出现异常,又通过“tx.rollback();"操作来撤销事务(事务回滚)。

  除了在代码中对事务开启,提交和回滚操作外,还可以在hibernate的配置文件中对事务进行配置。配置文件中,可以设置事务的隔离级别。其具体的配置方法是在hibernate.cfg.xml文件中的<session-factory>标签元素中进行的。配置方法如下所示。

  <!-- 
    事务隔离级别
hibernate.connection.isolation = 4
1-Read uncommitted isolation
2-Read committed isolation
4-Repeatable read isolation
8-Serializable isolation
-->
<property name="hibernate.connection.isolation">4</property>

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

    

  在Dao层操作数据库需要用到session对象,在Service控制事务也是使用session对象完成. 我们要确保Dao层和Service层使用的使用同一个session对象。

  有两种办法可以实现:

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

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

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

 <!-- 配置session与当前线程绑定 -->
<!-- thread:Session对象的生命周期与本地线程绑定(推荐)
jta:Session对象的生命周期与JTA事务绑定
managed:hibernate委托程序来管理Session对象的生命周期。
-->
<property name="hibernate.current_session_context_class">thread</property>

  注意:上述配置一般和sessionFactory.getCurrentSession()这个方法一起配合使用。getCurrentSession()方法用来绑定session和ThreadLocal,而且这个与线程绑定的session可以不用关闭,当事务提交时,session会自动关闭,不要手动调用close关闭。

Hibernate学习笔记(三)—— Hibernate的事务控制的更多相关文章

  1. Hibernate学习笔记三

    1.1.1 Hibernate的关联关系映射:(多对多) 1.1.1.1 多对多的配置: 步骤一创建实体和映射: Student: public class Student { private Int ...

  2. hibernate学习笔记之四 Hibernate的增删改查

    采用JUnit测试,继承TestCase import java.util.Date; import junit.framework.TestCase; import org.hibernate.Se ...

  3. Hibernate学习笔记(六) — Hibernate的二级缓存

    我们知道hibernate的一级缓存是将数据缓存到了session中从而降低与数据库的交互.那么二级缓存呢? 一.应用场合 比方.在12306购票时.须要选择出发地与目的地,假设每点一次都与数据库交互 ...

  4. Hibernate学习笔记三:对象关系映射(一对一,一对多,多对一,多对多)

    如需转载,请说明出处:http://www.cnblogs.com/gudu1/p/6895610.html Hibernate通过关系映射来表示数据库中表与表之间的关系,关系映射可以通过两种方式:配 ...

  5. Hibernate学习笔记三 多表

    一对多|多对一 表中的表达 实体中的表达 实体代码: package com.yyb.domain; import java.util.HashSet; import java.util.Set; p ...

  6. Hibernate学习笔记三:常用数据库操作语句

    转载请注明原文地址: 一:HQL 1:HQL语句格式:select from POJO类名 where 条件表达式 group by 属性 having 聚集函数 order by 属性 [其中,fr ...

  7. hibernate学习笔记之一 hibernate简介

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架 hibernate可以自动生成SQL语句,自 ...

  8. Hibernate学习笔记(二)

    2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...

  9. Hibernate学习笔记-Hibernate HQL查询

    Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...

  10. Hibernate学习笔记(一)

    2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...

随机推荐

  1. duck typing

    在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格.在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决 ...

  2. 设置html页面不被浏览器缓存

    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" ...

  3. 用java和汇编开发一个hello world系统内核

  4. 09-nginx Rewrite语法详解

    和location类似,也是要负责URL解析的. rewrite  重写 nginx的配置非常多,nginx的第三方模块也非常非常多.不可能讲每一种模块的配置办法.通常碰到一个nginx的新问题你想怎 ...

  5. NFA/DFA算法

    1.问题概述 随着计算机语言的结构越来越复杂,为了开发优秀的编译器,人们已经渐渐感到将词 法分析独立出来做研究的重要性.不过词法分析器的作用却不限于此.回想一下我们的老师刚刚开始向我们讲述程序设计的时 ...

  6. 值得一做》关于数学与递推 BZOJ1002 (BZOJ第一页计划)(normal+)

    什么都不说先甩题目 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之 ...

  7. 9.hive聚合函数,高级聚合,采样数据

    本文主要使用实例对Hive内建的一些聚合函数.分析函数以及采样函数进行比较详细的讲解. 一.基本聚合函数 数据聚合是按照特定条件将数据整合并表达出来,以总结出更多的组信息.Hive包含内建的一些基本聚 ...

  8. selenium+phantomjs解析JS

    背景知识: PhantomJS 是一个基于WebKit的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, J ...

  9. nodelet的理解

    1.介绍 nodelet包可以为在相同进程中的多个算法之间实现零拷贝的传输方式. 这个包也提供了实现一个nodelet所需的nodelet基类以及用于实例化nodelet的NodeletLoader类 ...

  10. (转)关于Update语句的锁

    原文地址:http://www.cnblogs.com/wdfrog/p/3144020.html 环境:MSSQL2005,在Read Committed级别 语句A:begin tranUpdat ...