Hibernate的事务管理

事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰。作为一名软件设计师,必须了解事务并合理利用,以确保数据库保存正确、完整的数据。数据库向用户提供保存当前程序状态的方法,叫事务提交(commit);当事务执行过程中,使数据库忽略当前的状态并回到前面保存的状态的方法叫事务回滚(rollback)。

1  事务的特性

事务具备原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)4个属性,简称ACID。下面对这4个特性分别进行说明。

原子性:将事务中所做的操作捆绑成一个原子单元,即对于事务所进行的数据修改等操作,要么全部执行,要么全部不执行。

一致性:事务在完成时,必须使所有的数据都保持一致状态,而且在相关数据中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构都应该是正确的。

隔离性:由并发事务所做的修改必须与任何其他事务所做的修改相隔离。事务查看数据时数据所处的状态,要么是被另一并发事务修改之前的状态,要么是被另一并发事务修改之后的状态,即事务不会查看由另一个并发事务正在修改的数据。这种隔离方式也叫可串行性。

持久性:事务完成之后,它对系统的影响是永久的,即使出现系统故障也是如此。

2  事务隔离

事务隔离意味着对于某一个正在运行的事务来说,好像系统中只有这一个事务,其他并发的事务都不存在一样。在大部分情况下,很少使用完全隔离的事务。但不完全隔离的事务会带来如下一些问题。
更新丢失(Lost Update):两个事务都企图去更新一行数据,导致事务抛出异常退出,两个事务的更新都白费了。  脏数据(Dirty Read):如果第二个应用程序使用了第一个应用程序修改过的数据,而这个数据处于未提交状态,这时就会发生脏读。第一个应用程序随后可能会请求回滚被修改的数据,从而导致第二个事务使用的数据被损坏,即所谓的“变脏”。  不可重读(Unrepeatable Read):一个事务两次读同一行数据,可是这两次读到的数据不一样,就叫不可重读。如果一个事务在提交数据之前,另一个事务可以修改和删除这些数据,就会发生不可重读。  幻读(Phantom Read):一个事务执行了两次查询,发现第二次查询结果比第一次查询多出了一行,这可能是因为另一个事务在这两次查询之间插入了新行。针对由事务的不完全隔离所引起的上述问题,提出了一些隔离级别,用来防范这些问题。  读操作未提交(Read Uncommitted):说明一个事务在提交前,其变化对于其他事务来说是可见的。这样脏读、不可重读和幻读都是允许的。当一个事务已经写入一行数据但未提交,其他事务都不能再写入此行数据;但是,任何事务都可以读任何数据。这个隔离级别使用排写锁实现。  读操作已提交(Read Committed):读取未提交的数据是不允许的,它使用临时的共读锁和排写锁实现。这种隔离级别不允许脏读,但不可重读和幻读是允许的。  可重读(Repeatable Read):说明事务保证能够再次读取相同的数据而不会失败。此隔离级别不允许脏读和不可重读,但幻读会出现。  可串行化(Serializable):提供最严格的事务隔离。这个隔离级别不允许事务并行执行,只允许串行执行。这样,脏读、不可重读或幻读都可发生。
事务隔离与隔离级别的关系如表9-2所示。
表9-2  事务隔离与隔离级别的关系
隔 离 级 别 脏读(Dirty Read) 不可重读(Unrepeatable read) 幻读(Phantom Read)
读操作未提交(Read Uncommitted) 可能 可能 可能
读操作已提交(Read Committed) 不可能 可能 可能
可重读(Repeatable Read) 不可能 不可能 可能
可串行化(Serializable) 不可能 不可能 不可能
在一个实际应用中,开发者经常不能确定使用什么样的隔离级别。太严厉的级别将降低并发事务的性能,但是不足够的隔离级别又会产生一些小的Bug,而这些Bug只会在系统重负荷(也就是并发严重时)的情况下才会出现。
一般来说,读操作未提交(Read Uncommitted)是很危险的。一个事务的回滚或失败都会影响到另一个并行的事务,或者说在内存中留下和数据库中不一致的数据。这些数据可能会被另一个事务读取并提交到数据库中。这是完全不允许的。
另外,大部分程序并不需要可串行化隔离(Serializable Isolation)。虽然,它不允许幻读,但一般来说,幻读并不是一个大问题。可串行化隔离需要很大的系统开支,很少有人在实际开发中使用这种事务隔离模式。
现在留下来的可选的隔离级别是读操作已提交(Read Committed)和可重读(Repeatable Read)。Hibernate可以很好地支持可重读(Repeatable Read)隔离级别。
 
3  在Hibernate配置文件中设置隔离级别

JDBC连接数据库使用的是默认隔离级别,即读操作已提交(Read Committed)和可重读(Repeatable Read)。在Hibernate的配置文件hibernate.properties中,可以修改隔离级别:

#hibernate.connection.isolation 4

在上一行代码中,Hibernate事务的隔离级别是4,这是什么意思呢?级别的数字意义如下。

1:读操作未提交(Read Uncommitted) 2:读操作已提交(Read Committed) 4:可重读(Repeatable Read) 8:可串行化(Serializable)

因此,数字4表示“可重读”隔离级别。如果要使以上语句有效,应把此语句行前的注释符“#”去掉:

hibernate.connection.isolation 4

也可以在配置文件hibernate.cfg.xml中加入以下代码:

 <session-factory>
…..
//把隔离级别设置为4
<property name=” hibernate.connection.isolation”>4</property>
……
</session-factory>

在开始一个事务之前,Hibernate从配置文件中获得隔离级别的值。

 
4  在Hibernate中使用JDBC事务

Hibernate对JDBC进行了轻量级的封装,它本身在设计时并不具备事务处理功能。Hibernate将底层的JDBCTransaction或JTATransaction进行了封装,再在外面套上Transaction和Session的外壳,其实是通过委托底层的JDBC或JTA来实现事务的处理功能的。

要在Hibernate中使用事务,可以在它的配置文件中指定使用JDBCTransaction或者JTATransaction。在hibernate.properties中,查找“transaction.factory_class”关键字,得到以下配置:

# hibernate.transaction.factory_class  org.hibernate.transaction.JTATransactionFactory
# hibernate.transaction.factory_class  org.hibernate.transaction.JDBCTransactionFactory

Hibernate的事务工厂类可以设置成JDBCTransactionFactory或者JTATransactionFactory。如果不进行配置,Hibernate就会认为系统使用的事务是JDBC事务。

在JDBC的提交模式(commit mode)中,如果数据库连接是自动提交模式(auto commit mode),那么在每一条SQL语句执行后事务都将被提交,提交后如果还有任务,那么一个新的事务又开始了。

Hibernate在Session控制下,在取得数据库连接后,就立刻取消自动提交模式,即Hibernate在一个执行Session的beginTransaction()方法后,就自动调用JDBC层的setAutoCommit(false)。如果想自己提供数据库连接并使用自己的SQL语句,为了实现事务,那么一开始就要把自动提交关掉(setAutoCommit(false)),并在事务结束时提交事务。

使用JDBC事务是进行事务管理最简单的实现方式,Hibernate对于JDBC事务的封装也很简单。下面是一个在Hibernate中使用JDBC事务的例子:

try {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();  //在默认情况下,开启一个JDBC事物
for(int i=0; i<10; i++)  {
Student stu = new Student();
stu.setName("Student" + i);
session.save(stu);
}
tx.commit(); //提交事务
session.close();
} catch(Exception e) {…
tx.rollback();   //事务回滚
}
 
5  在Hibernate中使用JTA事务

JTA(Java Transaction API)是事务服务的J2EE解决方案。本质上,它是描述事务接口的J2EE模型的一部分,开发人员直接使用该接口或者通过J2EE容器使用该接口来确保业务逻辑能够可靠地运行。

JTA有3个接口,它们分别是UserTransaction接口、TransactionManager接口和Transaction接口。这些接口共享公共的事物操作,例如commit()和rollback(),但也包含特殊的事务操作,例如suspend()、resume()和enlist(),它们只出现在特定的接口上,以便在实现中允许一定程度的访问控制。

在一个具有多个数据库的系统中,可能一个程序会调用几个数据库中的数据,需要一种分布式事务,或者准备用JTA来管理跨Session的长事务,那么就需要使用JTA事务。下面介绍如何在Hibernate的配置文件中配置JTA事务。在hibernate.properties文件中设置如下(把JTATransactionFactory所在的配置行的注释符“#”取消掉):

hibernate.transaction.factory_class  org.hibernate.transaction.JTATransactionFactory
# hibernate.transaction.factory_class  org.hibernate.transaction.JDBCTransactionFactory

或者在hibernate.cfg.xml文件中配置如下:

<session-factory>
…..
<property name=” hibernate.transaction.factory_class”>
org.hibernate.transaction.JTATransactionFactory
</property>
……
</session-factory>

下面是一个应用JTA事务的例子:

javax.transaction.UserTransaction tx = null;
tx = new initialContext().lookup(” javax.transaction.UserTransaction ”) ;
tx.begin();
Session s1 = sf.openSession();
……
s1.flush();  s1.close();
Session s2 = sf.openSession();
……
s2.flush();  s2.close();
tx.commit();

Hibernate的事务管理的更多相关文章

  1. (转载)Hibernate的事务管理

    Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰.作为一名软件设计 ...

  2. spring与hibernate整合事务管理的理解

    在谈Spring事务管理之前我们想一下在我们不用Spring的时候,在Hibernate中我们是怎么进行数据操作的.在Hibernate中我们每次进行一个操作的的时候我们都是要先开启事务,然后进行数据 ...

  3. sping 对 hibernate进行事务管理--Annotation, xml, 大多数使用XML

    1. UserServiceTest.java: package com.bjsxt.service; import org.junit.Test; import org.springframewor ...

  4. Spring+SpringMVC+Hibernate小案例(实现Spring对Hibernate的事务管理)

    原文地址:https://blog.csdn.net/jiegegeaa1/article/details/81975286 一.工作环境 编辑器用的是MyEclipse,用Mysql数据库,mave ...

  5. Spring整合hibernate -声明事务管理

     目录 1 sessionFactory 注入HibernateTransactionManager 2 XML配置的配置 3 添加annotation-driven 4 引入JAR包 5在servi ...

  6. (转)Hibernate事务管理

    Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰.作为一名软件设计 ...

  7. [转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊

    原文地址:http://stamen.iteye.com/blog/1441758 有些人很少使用Spring而不使用Spring事务管理器的应用,因此常常有人会问:是否用了Spring,就一定要用S ...

  8. 24Spring_事务管理机制

    第一部分:Spring事务管理高层抽象接口 我们介绍三个接口:1.PlatformTransactionManager 2.TransactionDefinition  3.TransactionSt ...

  9. Spring对hibernate的事物管理

    把Hibernate用到的数据源Datasource,Hibernate的SessionFactory实例,事务管理器HibernateTransactionManager,都交给Spring管理.一 ...

随机推荐

  1. varnish安装和配置

    实验环境:CentOS7 Varnish是高性能开源的反向代理服务器和HTTP缓存服务器. #varnish服务器:172.16.252.142 [root@varnish localhost]#yu ...

  2. Spring Boot 专栏

    http://blog.csdn.net/column/details/spring-boot.html?&page=2

  3. C#动态给EXCEL列添加下拉选项

    Microsoft.Office.Interop.Excel.Application excel=new Microsoft.Office.Interop.Excel.Application(); M ...

  4. WSGI 简介(使用python描述)

    WSGI 简介 背景 Python Web 开发中,服务端程序可以分为两个部分,一是服务器程序,二是应用程序.前者负责把客户端请求接收,整理,后者负责具体的逻辑处理.为了方便应用程序的开发,我们把常用 ...

  5. Eclipse/MyEclipse下如何Maven管理多个Mapreduce程序?(企业级水平)

    不多说,直接上干货! 如何在Maven官网下载历史版本 Eclipse下Maven新建项目.自动打依赖jar包(包含普通项目和Web项目) Eclipse下Maven新建Web项目index.jsp报 ...

  6. css 雪碧图

    CSS Sprites在国内很多人叫css精灵,是一种网页图片应用处理方式.它允许你将一个页面涉及到的所有零星图片都包含到一张大图中去,这样一来,当访问 该页面时,载入的图片就不会像以前那样一幅一幅地 ...

  7. Flask01 初识flask、创建flask应用、flask启动配置

    1 什么是flask Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 . 百度百科:点击前往 中文文档: ...

  8. 嵌入式linux环境搭建

    花了两天时间,终于搭建好了板子上的linux驱动开发环境,不容易呀,做个笔记. 首先搭建PC上的编译环境,因为编译的驱动是在板子上运行的,第一步当然需要安装交叉编译器,即arm-none-linux- ...

  9. Umbraco项目发布错误 --More than one type want to be a model for content type authorize

    在开发项目时,解决方案下面包括三个项目 MyUmbracoProject MyUmbracoProject.Core MyUmbracoProject.FrontEnd 第一个项目MyUmbracoP ...

  10. 剑指Spring源码(三)俯瞰Spring的Bean的生命周期(大众版)

    距离上一次写Spring源码解析,已经过去了快要好几个月了,主要原因还是Spring的源码解析类文章太难写了,不像我先前写的什么CAS源码,AQS源码,LinkedBlockingQueue等等,这些 ...