Java事务

徐海蛟 教学

 

中间件处于应用软件和系统软件之间,是一种以自己的复杂换取企业应用简单化的可复用的基础软件。

在中间件产生以前,应用软件直接使用操作系统、网络协议和数据库等开发,开发者不得不面临许多很棘手的问题,如操作系统的多样性,繁杂的网络程序设计和管理,复杂多变的网络环境,数据分散处理带来的不一致性,性能和效率、安全问题等等。这些问题与用户的业务没有直接关系,但又必须解决,耗费了大量有限的时间和精力。

于是,有人提出将应用软件所要面临的共性问题进行提炼、抽象,在操作系统之上再形成一个可复用的部分,供成千上万的应用软件重复使用。这一技术思想最终形成为了中间件产品。

事务中间件有:

n       IBM CICS

n       BEA Tuxedo

n       J2EE服务器等等

n       Microsoft MTS(COM+)

n       东方通国内第一个交易中间件TongEASY

n       基于CORBAVisiBroker ...

 

1 Java事务概述

为了完成对数据的操作,企业应用经常要求并发访问在多个构件之间共享的数据。这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义):

(1)分布式访问一个单独的数据资源

(2)从一个单独的应用构件访问分布式资源。

在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元。在一个工作单元中, 操作的所有部分一起成功或失败并恢复。

 

通常的观念认为,事务仅与数据库相关。

通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。即:要么全部执行成功,要么撤销不执行。

 

既然事务的概念从数据库而来,那Java事务是什么?之间有什么联系?

 

实际上,一个Java应用系统,如果要操作数据库,则通过JDBC来实现的。增加、修改、删除都是通过相应方法间接来实现的,事务的控制也相应转移到Java程序代码中。因此,数据库操作的事务习惯上就称为Java事务。

2事务必要性

事务是为解决数据安全操作提出的,事务控制实际上就是控制数据的安全访问。一个简单例子:比如银行转帐业务,武汉账户A要将自己账户上的1000元转到深圳B账户下面,A账户余额首先要减去1000元,然后B账户要增加1000元。该交易的伪码表示如下:

              begin transaction

                  accountA := accountA - 1000

                  accountB := accountB + 1000

              commit transaction

假如在中间网络出现了问题,A账户减去1000元已经结束,B因为网络中断而操作失败,那么整个业务失败,必须做出控制,要求A账户转帐业务撤销。这才能保证业务的正确性,完成这个操走就需要事务,将A账户资金减少和B账户资金增加方到一个事务里面,要么全部执行成功,要么操作全部撤销,这样就保持了数据的安全性。

事务:所有步骤要么全部完成,要么一个都不做。否则数据完整性将被破坏。因为事务中的所有步骤被看作一个统一的整体,所以事务一般被定义为一个不可分割的工作单元。

3事务属性

(1)原子性(ATOMICITY): 一个事务要被完全的无二义性的做完或撤消。在任何操作出现一个错误的情况下,构成事务的所有操作的效果必须被撤消,数据应被回滚到以前的状态。

(2)一致性(CONSISTENCY): 一个事务应该保护所有定义在数据上的不变的属性(例如完整性约束)。在完成了一个成功的事务时,数据应处于一致的状态。换句话说,一个事务应该把系统从一个一致状态转换到另一个一致状态。举个例子,在关系数据库的情况下,一个一致的事务将保护定义在数据上的所有完整性约束。

(3)隔离性(ISOLATION): 在同一个环境中可能有多个事务并发执行,而每个事务都应表现为独立执行。串行的执行一系列事务的效果应该同于并发的执行它们。这要求两件事: 在一个事务执行过程中,数据的中间的(可能不一致)状态不应该被暴露给所有的其他事务。两个并发的事务应该不能操作同一项数据。数据库管理系统通常使用锁来实现这个特征。

(4)持久性(DURABILITY): 一个被完成的事务的效果应该是持久的。

 

       结束事务有两种方法:提交或者回滚。

当一个事务提交,数据修改被保存。

如果事务中有一个步骤失败,事务就回滚,这个事务中的已经执行的动作被撤销。例如在上面的伪码中,如果在处理第二步的时候硬盘驱动器崩溃,事务的第一步将被撤销。尽管事务失败,数据的完整性不会被破坏,因为帐目仍然保持平衡。

前面伪码中,begincommit标明了事务的界限。当设计一个企业Bean的时候,你要决定怎样通过容器管理或bean管理事务来指定事务界限。

3类型

Java事务的类型有三种:JDBC事务、JTA(Java Transaction API)事务、容器事务。

3.1 JDBC事务

JDBC事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。

JDBC事务中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动得到事务确认。为了能将多个SQL语句组合成一个事务,要将auto-commit模式屏蔽掉。在auto-commit模式屏蔽掉之后,如果不调用commit()方法,SQL语句不会得到事务确认。在最近一次commit()方法调用之后的所有SQL会在方法commit()调用时得到确认。

java.sql.Connection 提供了以下控制事务的方法:

public void setAutoCommit(boolean)     // 自动提交设置

public boolean getAutoCommit()            // 获取

public void commit()           // 提交

public void rollback()          // 回滚

 

一个形式化示例:

public int tranDemo(...) {

 ... // 获取数据源,获取连接conn

 try {

  conn.setAutoCommit(false);// 更改JDBC事务的默认提交方式

          ...

  // crud 操作:增、读、改、删SQL

  conn.commit();//提交JDBC事务

  conn.setAutoCommit(true);// 恢复JDBC事务的默认提交方式

 }

 catch (Exception ex) {

  conn.rollBack();// 回滚JDBC事务

  ex.printStackTrace();

 }

}

使用 JDBC 事务界定时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接,不能跨越多个数据库。

3.2 JTA事务

JTA是一种高层的,与实现无关的,与协议无关的API,应用程序和应用服务器可以使用JTA来访问事务。

JTA允许应用程序执行分布式事务处理: 在两个或多个网络计算机资源**问并且更新数据,这些数据可以分布在多个数据库上。JDBC驱动程序的JTA支持极大地增强了数据访问能力。

如果计划用JTA界定事务,那么就需要有一个实现 javax.sql.XADataSource javax.sql.XAConnection javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂,XAConnection是参与 JTA 事务的 JDBC 连接。

需要用应用服务器的管理工具设置 XADataSource 。从应用服务器和 JDBC 驱动程序的文档中可以了解到相关的指导。

J2EE 应用程序用 JNDI 查询数据源。一旦应用程序找到了数据源对象,它就调用 javax.sql.DataSource.getConnection() 以获得到数据库的连接。

XA 连接与非 XA 连接不同。一定要记住 XA 连接参与了 JTA 事务。这意味着 XA 连接不支持 JDBC 的自动提交功能。同时,应用程序一定不要对 XA 连接调用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() 。相反,应用程序应该使用 UserTransaction.begin() UserTransaction.commit() UserTransaction.rollback()

 

一个示例:

public int tranJTADemo(...) {

 ... // 获取数据源,获取连接conn

 UserTransaction tran = sessionContext.getUserTransaction();// 获得JTA事务

 try {

  tran.begin(); // 开始JTA事务

  ...

  // crud 操作:增、读、改、删SQL

  tran.commit(); // 提交JTA事务

 }

 catch (Exception ex) {

  tran.rollback();// JTA事务回滚

  ex.printStackTrace();

 }

}

3.3容器事务

容器事务主要是J2EE应用服务器提供的,容器事务大多是基于JTA完成,这是一个基于JNDI的,相当复杂的API实现。相对编码实现JTA事务管理,我们可以通过EJB容器提供的容器事务管理机制(CMT)完成同一个功能,这项功能由J2EE应用服务器提供。这使得我们可以简单的指定将哪个方法加入事务,一旦指定,容器将负责事务管理任务。通过这种方式我们可以将事务代码排除在逻辑编码之外,同时将所有困难交给J2EE容器去解决。使用EJB CMT的另外一个好处就是程序员无需关心JTA API的编码。

4三种事务差异

1JDBC事务控制的局限性在一个数据库连接内,但是其使用简单。

2JTA事务的功能强大,事务可以跨越多个数据库或多个DAO,使用也比较复杂。

3、容器事务,主要指的是J2EE应用服务器提供的事务管理,局限于EJB应用使用。

5总结

事务控制是构建J2EE应用不可缺少的一部分,合理选择应用何种事务对整个应用系统来说至关重要。一般说来,在单个JDBC 连接连接的情况下可以选择JDBC事务,在跨多个连接或者数据库情况下,需要选择使用JTA事务,如果用到了EJB,则可以考虑使用EJB容器事务。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值