一,事务的概念
事务处理是由以一个单一的逻辑单位完成的一系列操作,它可以由一系列的操作组成,如果在该单位包含的操作执行完毕后没有发生错误,那么它所作的改变就是永久的了。如果一旦有错误发生,它就会滚回,不会作任何修改或改变。
二,事务的特点(ACID)
Atomicity, Consistency, Isolation, and Durability · 1,原子性(Atomicity)
事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。 2,一致性 (Consistency)
事务在完成时,必须使所有的数据都保持一致状态。 3,隔离性 (Isolation)
由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。 4,持久性 (Durability)
事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。
三,oracle中的事务
Oracle在缺省情况下任何一个DML语句都会开始一个事务,直到用户发出Commit或Rollback操作,这个事务才会结束。在Oracle中,执行DDL语句(如Create Table、Create View等)时,会在执行之前自动发出一个Commit命令,并在随后发出一个Commit或者Rollback命令。
(1) 提交事务
提交一事务,即将在事务中由SQL语句所执行的改变永久化。在提交前,ORACLE已有下列情况: 在SGA的回滚段缓冲区已生成回滚段记录,回滚信息包含有所修改值的老值。 在SGA的日志缓冲区已生成日志项。这些改变在事务提交前可进入磁盘。 对SGA的数据库缓冲区已作修改,这些修改在事务真正提交之前可进入磁盘。 在事务提交之后,有下列情况:
对于与回滚段相关的内部事务表记录提交事务,并赋给一个相应的唯一系统修改号(SCN),记录在表中。
在SGA的日志缓冲区中日志项由LGWR进程写入到在线日志文件, 这是构成提交事务的原子事务。 在行上和表上的封锁被释放。 该事务标志为完成 。
注意:对于提交事务的数据修改不必由DBWR后台进程立即写入数据文件,可继续存储在SGA的数据库缓冲区中,在最有效时将其写入数据文件。
(2) 回滚事务
回滚事务的含义是撤消未提交事务中的SQL语句所作的对数据修改。ORALCE允许撤消未提交的整个事务,也允许撤消部分。
在回滚整个事务(没有引用保留点)时,有下列情况:
在事务中所有SQL语句作的全部修改,利用相应的回滚段被撤消。 所有数据的事务封锁被释放。
第 1 页 共 6 页
事务结束。
当事务回滚到一保留点(具有SAVEPOINT)时,有下列情况: 仅在该保留点之后执行的语句被撤消。
该指定的保留点仍然被保留,该保留点之后所建立的保留点被删除。
自该保留点之后所获取的全部表封锁和行封锁被释放,但指定的保留点以前所获取的全部数据封锁继续保持。
该事务仍可继续。 3) 保留点
保留点(savepoint)是在一事务范围内的中间标志,经常用于将一个长的事务划分为小的部分。保留点可标志长事务中的任何点,允许可回滚该点之后的工作。在应用程序中经常使用保留点;例如一过程包含几个函数,在每个函数前可建立一个保留点,如果函数失败,很容易返回到每一个函数开始的情况。在回滚到一个保留点之后,该保持点之后所获得的数据封锁被释放。
四,JDBC控制事务
在JDBC中怎样将多个SQL语句组合成一个事务呢?在JDBC中,打开一个连接对象Connection时,缺省是auto-commit模式,每个SQL语句都被当作一个事务,即每次执行一个语句,都会自动的得到事务确认。为了能将多个SQL语句组合成一个事务,要将auto-commit模式屏蔽掉。在auto-commit模式屏蔽掉之后,如果不调用commit()方法,SQL语句不会得到事务确认。在最近一次commit()方法调用之后的所有SQL会在方法commit()调用时得到确认。出现异常时,rollback对事务进行回滚。
五,EJB中的事务
(一) EJB中事务处理的属性有:Required,RequiresNew,Mandatory,NotSupported,Supports,Never. 1、Required:当客户端运行一个事务处理并调用EJB的一个方法,这个方法执行客户端的事务处理;当客户端没有启动一个事务处理,则EJB容器在执行这个方法之前启动一个新的事务处理.
2、RequiresNew:当客户端运行一个事务处理并调用EJB的一个方法时,容器管理器做如下操作: (1) 悬挂客户端的事务处理; (2) 开始一个新的事务处理; (3) 调用方法;
(4) 当方法结束,恢复客户端的事物处理.
当客户端没有启动一个事务处理,容器管理器在执行这个方法之前启动一个新的事务处理.
3、Mandatory: 当客户端运行一个事务处理并调用EJB的一个方法,这个方法在客户端的事务处理范围内被执行; 当客户端没有启动一个事务处理,容器管理器将会抛错(TransactionRequiredException); 4、NotSupported: 当客户端运行一个事务处理并调用EJB的一个方法,容器管理器在调用方法之前终止客户端的事务处理,当方法执行完,再恢复客户端的事务处理; 当客户端没有启动一个事务处理,容器管理器在调用方法时不启动事务处理.
5、Supports: 当客户端运行一个事务处理并调用EJB的一个方法,在运行方法时执行客户端的事务处理; 当客户端没有启动一个事务处理,容器管理器在调用方法时不启动事务处理.
6、Never: 当客户端运行一个事务处理并调用EJB的一个方法,容器管理器将抛出一个错误(RemoteException); 当客户端没有启动一个事务处理,容器管理器在调用方法时不启动事务处理.
(二) EJB事务的操作
如果声明一个bean的事务控制为TX_BEAN_MANAGED,则这个bean可以访问事务服务。当事务控制应用于单个的方法时这个控制只能应用于整个的bean. bean访问事务服务的能力不能只对某个方法起作用。因此一个方法声明事务控制为TX_BEAN_MANAGED,而另一个方法声明为其它不同
第 2 页 共 6 页
的事务控制是错误的。厂商的安装工具应该能检测到并报告这个错误。Bean分别通过初始化时setSessionContext()或setEntityContext()方法的参数 SessionContext或EntityContext来访问事务服务。这些接口都是EJBContext的子类。
EJBContext的定义如下:
Public interface javax.ejb.EJBContext { public Identity getCallerIdentity();
public boolean isCallerInRole(Identity other); public EJBHome getEJBHome(); public Properties getEnvironment();
public UserTransaction getUserTransaction() throwsIllegalStateException; public boolean getRollbackOnly(); public void set RollbackOnly(); }
一旦bean获得了一个UserTransaction的引用,就可以用这个引用管理自己的事务。有状态的会话bean的方法可以创建一个事务,而且不用终止事务就可以返回。如果还有线程调用bean的方法,容器检测是否有bean创建的活动的事务,如果被调用的事务是同一个事务,容器会允许该线程重新进入这个bean.如果bean在事务中且执行不同事务上下文的线程试图进入bean,容器会阻塞这个线程直到bean的事务终止。如果线程试图进入事务时bean不在事务中,线程会执行一个自己的事务,容器会挂起线程当前的事务以允许线程进入。一旦线程离开方法就会恢复线程以前的事务,容器不会终止任何方法创建的事务。
对于无状态会话bean和实体bean,当事务活动时bean的方法不允许返回。容器会为此抛出一个例外。
会话同步接口
有状态和无状态的会话bean都可以访问数据库,并且参与一个事务。为了让bean在事务中执行它的任务,bean开发者可以实现在bean中实现 javax.ejb.SessionSynchronization接口。容器能自动检测这个接口,容器会使用这个接口中的方法以使bean得到事务的状态信息。实体bean不支持这个接口。因为实体bean are implicitly transaction aware,所以容器使用不同的方法控制一个事务中的实体 bean.
SessionSynchronization接口定义如下: public interface javax.ejb.SessionSynchronization { public void afterBegin() throws RemoteException; public void beforeCompletion() throws RemoteException; public void afterCompletion(boolean yn) throws RemoteException; }
实际上一个事务不属于一个特殊的bean的实例。一个客户端或容器中执行的线程创建一个事务,在执行bean中的代码时执行该事务。如果一个有事务上下文的线程将要进入一个会话bean,容器首先调用它的afterBegin()方法。Bean可以记录所有的商业方法运行在事务中,随后执行事务操作。如果一个操作的内部标志显示这个线程在事务外运行,则会拒绝执行事务操作的请求。直到调用afterCompletion()方法,bean会继续认为商业方法的调用都在事务中执行。Bean将推断性地清除内部标志,以表示随后到来的事务请求将被拒绝。
第 3 页 共 6 页
如果一个事务上下文的线程试图进入一个已经是另一个事务的一部分的Bean时, .Container将封锁入口,直到前一个事务提交或回滚,并且afterCompletion()方法被调用,此时,允许Bean 恢复它的状态。Container负责提供这些行为。当Container发现它将要提交一个事务时,将在这个事务的所有的session Bean上调用beforeCompletion()方法。这就给Bean足够的机会来结束事务的操作,如在提交前将数据写入数据库。反之,当Container 发现,将要回滚一个事务撕,BeforeCompletion()方法将不会被调用,因为将一个将被回滚的事务所产生的数据写入数据库是没有意义 的。
AfterCompletion()是在一个事务即将提交或回滚时被调用,来通知Bean事务操作的最终结果。Bean可以用这个信息来修正自己的内部状态,但它不能用这个信息来维持任何它将要保存的事务。尽管session Bean可以创建,提交和回滚它自己的事务,但通常不推荐这样做。
SessionSynchronization接口不提供整合外部和内部事务的能力。如果一个session bean实现了这个接口,则意味着它在方法调用之间要保持事务的状态。特别地,这也暗示在afterBegin()和afterCompletion()调用之间bean是处于一个事务中。这样,如果一个bean实现了SessionSynchronization接口并且在装配符中声明是无状态的就是一个错误。厂商提供的安装工具应该可以捕捉到并报告这个错误。无状态的session bean可以加入一个事务,但它们不能实现这个接口。事务可以是TX_BEAN_MANAGED,或者container可以在方法入口和从方法的返回上来开始和提交这个事务。Container不可允许在一个现存的事务中有一个线程进入方法,因为无状态的Bean的方法将无法知道正在运行的线程是否正在一个事务中。
解决这个问题的一个方法是使container挂起现存的事务,强迫方法总是认为线程没有在一个事务性的上下文中运行。有状态的Bran可以不实现这个接口而介入事务。但是,装配符必须要认真地配置以使得商务方法总能在正确的事务状态中运行。Bean自己没有通过这个接口来获得自己的事务的状态的权利。
加入事务
EJBContext接口在前面的一节中已经介绍了。其中有两个方法: public boolean getRollbackOnly(); public void setRoolbackOnly();
这些方法可以有任何bean来使用,而不仅仅是那些声明了其事务控制为bean-managed的bean。事实上,那些处理自己的事务的bean将不会用到这些方法,因为这些方法不是用来和外界的事务管理器进行交流事务状态的。
当一个bean调用了setRollBackOnly()方法时,它是在向事务管理器询问何时结束将要回滚的当前事务。它将给它所参与的事务的结果一个选票。这些方法还存在于UserTransaction接口中,但由于大多数的bean都不访问这个接口,这些方法必须直接地在EJBContext中提供给bean。注意这个方法并不引发回滚操作,它只是简单地设置标志,表示事务在结束时应该回滚。不象JavaBan属性设置方法,这个方法不以boolean值作为参数。这个方法是特意设计成这样,以使得一个bean不能够改变另一个bean的回滚请求。一个bean也许希望使用getRoolBackOnly()方法,来检查当前的事务的状态。如果另一个bean已经标志这个事务为rollback,则正在调用的bean可以推测到并决定不能执行那些在、强制性达到操作,如数据库更新,而这些操作很有可能在事务结束时被反转过来。
客户划分的事务
尽管一个JEB厂商所必须的,大服务器厂商也许决定提供一个类,使得用户可以直接访问事务管理器。当需要在同一个上下文中在两个不同的服务器上调用bean时,用户也许会希望这样做。当然,每个bean的装配符可以允许这样的行为。用户可以创建一个事务,然后在两个不同server上的
第 4 页 共 6 页
两个不同的bean上调用商务方法,而将事务的上下文也作为调用的一部分进行传递。一旦调用结束,用户将推测地结束事务。有container厂商产生的stub和skeleton将支持事务上下文的隐式传递。
这里是一个可能的例子: Current current = new Current(); Current.setServiceProvider(txMgrURL); Current.create(); Current.begin(); Current.doSomeWork(); RemRef1.doSomeWork(); RemRef2.doMoreWork(); Current.commit(); 数据库操作的事务管理
bean当然希望使用JDBC来建立到数据库的连接,并在其上进行操作。但是,为了符合EJB这种container管理事务的模式,连接不能使用自动提交特性,并且不应该在连接上试图提交或回滚。
Container的角色是决定在这个事务中执行的所有行为应该提交还是回滚。这里提这样一个问题很好:container如何看到并管理由bean方法内部创建的数据库连接。尽管在规范中没有明确地提到,EJB将只能使用JDBC驱动,而JDBC也正是用来和EJB配合使用的。在数据库连接的创建时,驱动程序透明地将连接注册到正在执行的线程的当前事务中。之后当container决定结束事务时,数据库连接将自动地结束它。用OTS的术语说,数据库连接是不可恢复的资源,有事务服务在container的协助下,隐式地管理。尽管可以在这种情况下使用非事务感知的JDBC Driver,但开发者必须清楚任何在数据库连接上所做的操作都不属于bean的事务,开发者还必须确保在从方法返回之前结束数据库连接事务。试图使用SessionSynchronization接口来合并数据库连接事务和bean本身的事务是不可靠的,是不应该作的。
分布事务的支持
一个分布事务在下面的情况下是需要的:
. 一个用户使用用户划分的在多个server上的多个bean中创建和调用方法的事务。 . 一个在其他的server上调用其他EJB的方法的bean的方法。
对于这些工作厂商必须为EJBObject生成stub和skeleton来隐式地获得当前事务的上下文,同时将其通过方法调用传到远程bean。当将商务方法调用委派给bean时,远程bean的EJBObject的skeleton必须请求这个事务的上下文
六,JTA事务管理方式
Java事务API(Java Transaction API,JTA)用于为EJB组件提供与数据库管理器无关的事务组件管理方式。JTA作为Java事务服务(Java Transaction Service,JTS)的高层应用编程接口,使得在组件程序设计过程中可以利用JTA中的相应方法控制组件的事务范围以及事务管理方式。请读者看下面的代码:
public void doAnotherThing(){
UserTransaction ut = context.getUserTransaction(); try{
第 5 页 共 6 页
ut.begin();
demoBusinessMethod(); ut.commit();
}catch (Exception exp){ try{
ut.rollback();
}catch(SystemException exp1){
throw new EJBException(\"Rollback failed: \" + exp1.getMessage()); }
throw new EJBException(\"Transaction failed: \" + exp.getMessage()); } }
在上面的代码中,读者首先看到用户事务接口对象UserTransaction。在该接口中定义了用于确定组件事务范围以及控制组件事务过程的begin、commit和rollback方法。在组件方法执行之前首先调用UserTransaction接口中的begin方法确定组件的事务过程开始,在组件商务方法执行过程中如果没有发生异常,则调用commit方法提交事务范围内方法的运行结果,否则调用rollback方法将方法运行结果回滚并抛出EJBException类型异常。 事务管理方式总结
对于不同类型的EJB组件,在组件开发和组装可以选择不同的组件事务管理方式。下表对不同类型EJB组件适用的事务管理方式进行了总结: 表1 组件类型与可选事务管理方式汇总表 组件类型 容器事务管理方式 组件事务管理方式 JDBC JTA 会话组件 Y Y Y 实体组件 Y N N 消息驱动组件 Y Y Y
从上表可以看出:除了实体组件不能采用JDBC和JTA事务管理方式外,其它任何事务管理方式均适用于所有类型的EJB组件。 七,使用事务的技巧:
(1) 一个事务不要涉及太多的操作. (2) 容器管理和bean管理的事务
事务既耗费应用服务器中的资源,又耗费数据库资源,所以事务越短越好. 尽量使用容器管理事务而不要采用bean管理事务的方式.
(3) ejb遇到错误,需要强制事务回滚. 使用EJBObject.setRollbackOnly(); (4) 不能让事务涉及web层和表示逻辑
(5) 企业应用中不应当选用supports 事务属性,因为只有调用者开始一个事务后,ejb才能在事务中运行.
第 6 页 共 6 页
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo7.cn 版权所有 湘ICP备2022005869号-9
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务