Hibernate事务控制.docx

上传人:b****2 文档编号:24098594 上传时间:2023-05-24 格式:DOCX 页数:6 大小:17.99KB
下载 相关 举报
Hibernate事务控制.docx_第1页
第1页 / 共6页
Hibernate事务控制.docx_第2页
第2页 / 共6页
Hibernate事务控制.docx_第3页
第3页 / 共6页
Hibernate事务控制.docx_第4页
第4页 / 共6页
Hibernate事务控制.docx_第5页
第5页 / 共6页
点击查看更多>>
下载资源
资源描述

Hibernate事务控制.docx

《Hibernate事务控制.docx》由会员分享,可在线阅读,更多相关《Hibernate事务控制.docx(6页珍藏版)》请在冰豆网上搜索。

Hibernate事务控制.docx

Hibernate事务控制

4.7事务控制

每个业务逻辑方法都是由一系列的数据库访问完成,这一系列的数据访问可能会修改多条数据记录,这系列的修改应该是一个整体,绝不能仅修改其中的几条。

也就是说,多个数据库原子访问应该绑定成一个整体——这就是事务。

事务是一个最小的逻辑执行单元,整个事务不能分开执行,要么同时执行,要么同时放弃执行。

4.7.1事务的概念

事务是一步或几步基本操作组成的逻辑执行单元,这些基本操作作为一个整体执行单元,它们要么全部执行,要么全部取消,绝不能仅仅执行部分。

一般而言,每次用户请求,对应一个业务逻辑方法,一个业务逻辑方法往往具有逻辑上的原子性,应该使用事务。

例如,一个转账操作,对应修改两个账户的余额,这两个账户的修改要么同时生效,要么同时取消——同时生效是转账成功,同时取消是转账失败;但不可只修改其中一个账户,那将破坏数据库的完整性。

通常来讲,事务具备如下4个特性:

原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持续性(durability)。

这4个特性也简称为ACID性。

  ●原子性:

事务是应用中最小执行单位,就如原子是自然界最小颗粒,具有不可再分的特征一样。

事务是应用中不可再分的最小逻辑执行体。

  ●一致性:

事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。

当数据库只包含事务成功提交的结果时,数据库处于一致性状态。

如果系统运行发生中断,某个事务尚未完成而被迫中断,而该未完成的事务对数据库所做的修改已被写入数据库,此时,数据库就处于一种不正确的状态。

比如银行在两个账户之间转账,从A账户向B账户转入1000元。

系统先减少A账户的1000元,然后再为B账户增加1000元。

如果全部执行成功,数据库处于一致性状态。

如果仅执行完A账户金额的修改,而没有增加B账户的金额,则数据库就处于不一致性状态。

因此,一致性是通过原子性来保证的。

  ●隔离性:

各个事务的执行互不干扰,任意一个事务的内部操作对其他并发的事务,都具有隔离性。

也即并发执行的事务之间不能互相影响。

  ●持续性:

持续性也称为持久性(persistence),指事务一旦提交,对数据所做的任何改变,都要记录到永久存储器中,通常保存进物理数据库。

4.7.2Hibernate的事务

Hibernate直接使用JDBC连接和JTA资源,不添加任何附加锁定行为。

Hibernate只添加自动版本管理,而不会锁定内存中的对象,也不会改变数据库事务的隔离级别。

基本上,使用Hibernate就好像直接使用JDBC(或者JTA/CMT)进行数据库访问。

Hibernate中SessionFactory对象的创建代价很高,它是线程安全的对象,被设计成可以为所有的应用程序线程所共享。

通常,SessionFactory会在应用程序启动时创建,一旦创建了SessionFactory将不会轻易关闭,只有当应用关闭时,SessionFactory才会关闭。

而Session的对象是轻量级的,它也是线程不安全的。

对于单个业务进程单个工作单元而言,Session只被使用一次。

创建Session时,并不会立即打开与数据库之间的连接,Session只在需要进行数据库操作时,才会获取JDBC连接。

因此,打开和关闭Session,并不会对性能造成很大的影响。

甚至即使无法确定一个请求是否需要数据访问,也可以打开Session对象,因为如果不进行数据库访问,Session不会获取JDBC连接。

相反,数据库事务应该尽可能的短。

从而,降低数据库锁定造成的资源争用。

数据库长事务会导致应用程序无法承载高并发的负荷。

由上面的介绍可知,Hiberante的Session和事务是紧密相关的,因为事务是通过Session来打开的。

那么事务的范围是多大?

单个Session可以跨越多个数据库事务吗?

事务和Session的对应关系又如何呢?

下面将介绍HibernateSession和事务的关系。

4.7.3事务和Session

数据库操作必须在Hibernate的Session管理下进行,但不推荐因为一次简单的数据库原子调用,就打开和关闭一次Session,数据库事务也是如此。

因为,对于一次原子操作打开的事务没有任何意义——事务应该是将多个操作步骤组合成一个逻辑整体。

事务是按顺序发送并组成一个逻辑整体的原子操作单元。

注意:

也就是说单个的SQL语句发送之后,自动事务提交模式失效了。

这种自动提交模式仅为SQL控制台设计,在实际项目没有太大的实用价值。

Hibernate禁止事务立即自动提交模式,或者让应用服务器禁止事务自动提交。

通常,建议每个请求对应一个Session。

在这种模式下,来自客户端的请求被发送到服务器端,此处可能对应一个业务逻辑方法。

在这个业务逻辑方法内,一个新的HibernateSession被打开,然后开始事务,在事务内执行这个操作单元中所有的数据库操作。

一旦操作完成,需要发送给客户端的响应也准备就绪。

此时,提交事务,然后关闭Session。

在这种模式下,Session和用户请求是一对一的关系,这是一种理想的Session管理模式。

为了达到这种效果,推荐使用一个ThreadLocal变量,把Session绑定到处理客户端请求的线程上去。

这种方式可以让运行在该线程上的所有程序代码轻松地访问Session。

也可以在一个ThreadLocal变量中保持事务上下文环境,不过这依赖于所选择的数据库事务划分机制。

这种实现模式被称之为ThreadLocalSession和OpenSessioninView。

下面是一个HibernateUtil类,该类将HibernateSession存放在一个ThreadLocal变量中,对于同一个线程的请求,将可以轻松访问该Session。

publicclassHibernateUtil

{

   publicstaticfinalSessionFactorysessionFactory;

   //静态初始化块,使用该类时使用该代码块

   static

   {

       try

       {

           //采用默认的hibernate.cfg.xml来启动一个Configuration的实例

           Configurationconfiguration=newConfiguration().configure();

           //由Configuration的实例来创建一个SessionFactory实例

           sessionFactory=configuration.buildSessionFactory();

       }

       catch(Throwableex)

       {

           System.err.println("初始化sessionFactory失败."+ex);

           thrownewExceptionInInitializerError(ex);

       }

   }

   //ThreadLocal是隔离多个线程的数据共享,不存在多个线程之间共享资源,因此不再需要

   对线程同步

   publicstaticfinalThreadLocalsession=newThreadLocal();

   //该方法用于获取当前线程的Session对象

   publicstaticSessioncurrentSession()throwsHibernateException

   {

       Sessions=(Session)session.get();

       //如果该线程还没有Session,则创建一个新的Session

       if(s==null)

       {

           s=sessionFactory.openSession();

           //将获得的Session变量存储在ThreadLocal变量的Session里

           session.set(s);

       }

       returns;

   }

   //该方法用于关闭当前线程里的Session

   publicstaticvoidcloseSession()throwsHibernateException

   {

       Sessions=(Session)session.get();

       if(s!

=null)

           s.close();

       session.set(null);

   }

}

在上面的代码中,HibernateSession被绑定到当前线程。

当调用currentSession方法时,如果当前线程中的Session已经创建出来,那么将返回这个已经存在的Session实例。

每次请求对应一个Session的模式不仅可以用于设计操作单元,甚至很多业务处理流程都需要组合一系列的用户操作,即用户对数据库的交叉访问。

但是,对于企业应用,跨用户交互的数据库事务是无法接受的。

例如,在第一个页面,用户打开对话框,打开一个特定Session装入的数据,可以随意修改对话框中的数据,修改完成后,将修改结果存入数据库。

从用户的角度来看,这个操作单元被称为应用程序长事务。

在一个J2EE应用实现中,可以有很多方法来实现这种应用程序长事务。

一个比较差的做法是,当用户思考时,应用程序保持Session和数据库事务是打开的,并保持数据库锁定,以阻止并发修改,从而保证数据库事务隔离级别和原子操作。

这种数据库锁定会导致应用程序无法扩展并发用户的数目。

因此,不要使用每个应用对应一次HibernateSession的模式,也不要使用每次HttpSession对应一次HibernateSession的模式。

注意:

几乎所有情况下,都不要使用每个应用对应一次HibernateSession的模式,也不要使用每次HttpSession对应一次HibernateSession的模式。

对于这种情况,Hibernate主要有如下两种模式来解决这个问题:

  ●脱管对象,如果采用每次用户请求对应一次Session的模式。

那么,前面载入的实例在用户思考的过程中,始终与Session脱离,处于脱管状态。

都处于与Session脱离的状态。

Hibernate允许把脱管对象重新关联到Session上,并且对修改进行持久化。

在这种模式下,自动版本化被用来隔离并发修改。

这种模式也被称为使用脱管对象的每个请求对应一个HibernateSession。

  ●长生命周期Session,Session可以在数据库事务提交之后,断开和底层的JDBC连接。

当新的客户端请求到来时,它又重新连接上底层的JDBC连接。

这种模式被称为每个应用程序事务对应一个Session,因为应用程序事务相当长(跨越多个用户请求),所以也被称为每次应用事务对应一个HibernateSession。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 其它考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1