浅琢Container-Managed Transaction
来源:互联网 发布:贺林院士怎么样 知乎 编辑:程序博客网 时间:2024/06/10 03:14
事务处理分Container-Managed Transaction和Bean-Managed Transaction。
Container-Managed Transaction
由EJB容器来管理事务的开始与结束。在这种情形底下,事务可以处理各种企业Bean:会话,实体或者消息驱动。由EJB容器来管理,简化了开发,代码无需显式地声明事务处理的开始和结束。
在企业Bean的某个方法调用之前,容器立即启用一个事务,在该方法退出的时候,容器会提交事务。每个方法都会有一个特定的事务来处理,每个事务都由容器自动管理。但是在方法体内部,不支持嵌套的或者多个事务。
基于容器的事务管理并不强迫每个方法都必须有一个事务来监督,我们可以设置事务属性来区别对待各自的方法。
Transaction Attributes
事务属性决定了事务的作用范围,有以下值:
Required
RequiresNew
Mandatory
NotSupported
Supports
Never
Required:
在Required情况下,假设Client在一个事务中运行并且调用了一个企业Bean的某个方法,那么这个方法也将由这个事务来处理。反之,如果Client运行的时候没有事务来管理,那么在调用Bean的方法之前,容器会自动启用一个事务机制。
RequiresNew:
如果Client在一个事务处理中调用Bean的方法,容器会采取如下步骤来处理:
1)挂起Client的事务
2)启用新的事务
3)访问Bean方法
4)Bean方法结束之后恢复Client的事务
如果Client没有使用transaction,那么容器会在Client调用Bean之前启用一个新的事务。
Mandatory:
如果Client在事务中调用Bean方法,那么Bean方法会在该事务中处理。否则,容器会抛异常错:TransactionRequiredException
NotSupported:
如果Client使用transaction,此时它在调用Bean方法时,容器会挂起该事务。在Bean结束后,恢复事务。如果Client没有使用transaction,容器也不会自动启用新的事务。
在这种属性之下,事务不起任何作用,会大大提高运行性能。
Supports
如果Client使用了事务处理,它在调用Bean方法时,该方法也会交由该事务来处理。反之,Client没有使用事务,容器也不会启用新的事务。
Never
不允许任何事务存在。一旦存在,容器会抛RemoteException。
何时设置事务属性
因为transaction attributes是保存在容器的descriptor中的,所以各级开发人员在任何时候都可以修改它。事实上,只有企业Bean的开发人员才能修改该属性,因为只有他们明白事务需要如何处理。所以不要指望企业应用发布人员在deploy的时候去指定。
Roll back事务
有两种方法可以回滚。一是系统在抛出异常的时候,容器可以自动取消该事务的执行;二是显式地代码声明:
EJBContext(interface).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());
}
}
使用银行卡在借记账户和消费账户之间转账,某个时刻,消费卡被转账成透支状态(checkingBalance < 0.00),就马上取消该事务。
注意在该方法中,实体Bean是很容易被rollback,因为涉及的是数据库操作。对于一个会话Bean来说,必须额外处理,方法是重置SessionSynchronization接口的一个实例变量。
会话Bean的回滚
使用SessionSynchronization可以同步化对应着数据库中数据的各个实例变量。容器按照如下的顺序来调用SessionSynchronization的各个方法。
afterBegin, beforeCompletion, afterCompletion
afterBegin通知实例有一个新的事务已经开始,在调用各种商业逻辑之前,容器立即执行afterBegin。可以说,afterBegin是最好的加载各个数据变量的方法,例如:
public void afterBegin() {
System.out.println("afterBegin()");
try {
checkingBalance = selectChecking();
savingBalance = selectSaving();
} catch (SQLException ex) { throw new EJBException("afterBegin Exception: " + ex.getMessage());}
}
该方法加载了两个变量checkingBalance 和savingBalance 。
在各种商业逻辑执行完后,容器立即调用beforeCompletion方法。此时,该方法是能够回滚事务的最后一个地方,如果它还没有执行更新数据库之类的操作,回滚就是有效的。最后容器调用afterCompletion,根据boolean变量来判断是commit还是rollback,例子如下:
public void afterCompletion(boolean committed) {
System.out.println("afterCompletion: " + committed);
if (committed == false) {
try {
checkingBalance = selectChecking();
savingBalance = selectSaving();
} catch (SQLException ex) {
throw new EJBException("afterCompletion SQLException: " + ex.getMessage());
}
}
}
此处rollback是仍然调用和afterBegin中一样的两个方法,即重新从数据库中加载数据。
一些注意点
使用容器来自动管理事务处理,必须显式地杜绝一些容易干扰事务处理的方法,比如jdbc中commit, setAutoCommit, 和rollback方法;javax.ejb.EJBContext中的getUserTransaction方法;javax.transaction.UserTransaction的任何调用等。
- 浅琢Container-Managed Transaction
- Rolling Back a Container-Managed Transaction
- EJB (四) EJB Container Manage Transaction
- Container-managed relations for the 21st century
- EJB-CMT-Container-Managed Transactions官网原文
- Eclipse3.2.1中利用XDoclet Enterprise JavaBean创建Container Managed Entity Bean
- Transaction
- Transaction
- Transaction
- transaction
- Transaction
- Transaction
- Transaction
- Transaction
- @Transaction
- transaction
- Transaction
- Container
- 杂
- java基础知识
- 杂2
- VB程序中用ADO对象动态创建数据库和表
- 思维分析
- 浅琢Container-Managed Transaction
- JS的一些细节
- JSF自定义验证器标签
- 转:设计模式与篮球
- 找个地方放东西
- 表关系(一对一,一对多,多对多)
- 掌握VB中的ADO数据对象编程
- VB指针技术
- 富人的几个特征