一个典型的企业应用程序在一个或多个数据库里取数据和储存数据.这些数据对于商家来说是非常重要的,所以要保证它的正确性,当前性,可靠性.而当多个程序同时修改和更新同一个数据时,可能会造成数据的丢失.当一个数据库的更新失败,数据库中的数据因为部分的更新而造成数据的丢失.为了防止出现上述情况,引入了事务处理的概念来保证数据的完整性.它控制多个程序同时访问数据. |
为了进行事务处理,必须有以下几步,现在以一个银行的金融管理程序为例: |
一、开始事务处理 |
1. 借方检查帐号 |
2. 信任储蓄存款帐号 |
3. 更新日志文件 |
二、提交事务处理结果 |
上例必须在三步全部做完,数据才提交,否则数据将会丢 失.一个事务处理在两种情况下结束:提交或恢复.当一个事务处理被提交,数据的修改将被保存;当一个事务处理中失败,这个事务处理将被结束并将数据恢复到以前的状态.举上面的例子,当在第二步(信任储蓄存款帐号)时发现有错,则处理中断并将数据恢复到开始的状态.所以尽管事务处理失败,但数据没有发生错误. |
在J2EE中的EJB是靠容器管理界面去管理事务.可以通过容器去设置任何类型的EJB(Session,Entity,messge-drive)的事务.用容器去管理事务非常方便,并且不需要在EJB中添加额外的代码. |
当EJB中的一个方法被调用时,容器管理器开始一个事物处理过程.它在方法调用完成时提交事务处理结果.每个方法都可以设置事务处理.在一个方法里面不允许嵌套的或多个事务处理. |
一个事务处理的属性控制它本身的范围.如: |
|
方法A开始一个事务处理并调用方法B.当方法B被执行的时候,它是在方法A的事务处理的范围内还是启动一个新的事务处理呢?这就是要靠事务处理的属性来控制. |
一个事务处理的属性有: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产生阶段;应用程序整合阶段;配置阶段.如我们可以在配置的时候指定: |
|
你可以指定个别方法的事务处理属性或整个EJB的事务处理属性.当你指定方法的某个事务处理的属性和另外的EJB的事务处理属性时,方法的事务处理属性优先. |
当事务处理失败时,有两种方式恢复一个容器管理器的事务处理.第一,如果系统抛出一个错误,容器管理器自动恢复;第二,调用setRollbackOnly方法,命令容器管理器恢复事务处理.下面是一个例子: |
public void transferToSaving(double amount) throws |
InsufficientBalanceException { |
checkingBalance -= amount; |
savingBalance += amount; |
try { |
updateChecking(checkingBalance); |
if (checkingBalance < 0.00) { |
context.setRollbackOnly();//恢复 |
throw new InsufficientBalanceException(); |
} |
updateSaving(savingBalance); |
} catch (SQLException ex) { |
throw new EJBException |
("Transaction failed due to SQLException: " |
+ ex.getMessage()); |
} |
} |
J2EE容器管理器控制除了JDBC以外的所有的EJB事务处理.它可以使一个EJB在一个事务处理时更新多个数据库.下面的例子是关于在一个单一的事务处理中更新多个数据库: |
|
(1) |
在上例1中客户调用Bean-A的一个方法,这个方法启动一个事务处理,更新数据库X和数据库Y,并调用Bean-B中的一个方法,在Bean-B的方法中更新数据库Z并返回Bean-A.在Bean-A中提交事务处理. |
|
(2) |
在上例中2客户调用Bean-A中的一个方法,在这个方法中开始一个事务处理,更新数据库X,并调用远端J2EE的Bean-B的方法,在Bean-B中更新数据库Y.J2EE管理器能保证多个数据库的更新能在一个事务处理中完成. |