EJB 3事务之容器管理事务(CMT)BE…
2013-07-12 22:54
281 查看
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
容器管理事务(Container-Managed Transaction, CMT
):容器管理事务允许组件自动征集(enlist
)到事务中,也就是说,EJB
组件从不需要显式地给出begin 、commit 、abort
语句,EJB 容器会替开发者考虑这些内容。EJB
容器会依据EJB
组件提供者指定的事务行为来界定相应的事务边界。在使用容器管理事务时,EJB
容器会拦截客户请求,并自动为EJB
组建启动新的事务,也就是说,容器会通过begin
语句调用底层事务系统,从而启动事务。随后,容器会将业务请求委派给EJB
组件,组件中的业务操作将运行在这一事务中。处于事务中的EJB
组件能够执行任何业务逻辑,如写入数据库、发送异步信息、调用其他的EJB
组件等。一旦在处理业务过程中出现问题,则EJB
组建需要通知EJB 容器去回滚事务。当EJB
组建完成业务处理后,会将控制权交回给EJB
容器。随后,EJB 容器能够通过commit 或abort
语句调用底层事务系统。
通过使用@TransactionAttribute
注释或部署描述符,开发者能够指定事务属性。EJB
容器通过分析事务属性便能够知道如何处理EJB
组件的事务需求。EJB 事务属性的取值有:
(1 )Required ,如果EJB
组件必须总是运行在事务中,则应该使用Required
模式。如果已经有事务在运行,则EJB
组件参与其中;如果没有事务运行,则EJB
容器会为EJB 组件启动新的事务。
Required
是默认和最常使用的事务属性值。这个值指定必须在事务之内调用EJB
方法。如果从非事务性客户端调用方法,那么容器会在调用方法之前开始事务,并且在方法返回时结束事务。另一方面,如果调用者从事务性上下文调用方法,那么
方法会联结已有事务。在从客户段传播事务的情况下,如果我们的方法表示应该回滚事务,那么容器不仅回回滚整个事务,而且会向客户端抛出异常,从而让客户端
知道它开始的事务已经被另一个方法回滚了。
(2 )Requires_New ,当客户调用EJB
时,如果总是希望启动新的事务,则应该使用RequiresNew
事务属性,如果客户在调用EJB
组件时已经存在事务,则当前事务会被挂起,进而容器启动新的事务,并将调用请求委派给EJB
组件。也就是说,如果客户端已经有了事务,那么它暂停该事务,知道方法返回位置,新事务是成功还是失败都不会影响客户端已有的事务。EJB
组件执行相应的业务操作,容器会提交或回滚事务,最终容器将恢复原有的事务,当然,如果客户在调用EJB
组件时不存在事务,则不需要执行事务的挂起或恢复操作。
RequiresNew 事务属性非常有用。如果EJB
组件需要事务的ACID 属性,并且将EJB
组件运行在单个独立的工作单元中,从而不会将其他外部逻辑也包括在当前的事务中,则必须使用RequiredNew
事务属性。如果需要事务,但是不希望事务的回滚影响客户端,就应该使用它。另外,当不希望客户端的回滚影响你的时候,也应该使用这个值。日志记录是个很好
的例子,即使父事务回滚,你也希望把错误情况记录到日志中,另一方面,日志记录细小调试信息的失败不应该导致回滚整个事务,并且问题应该仅限于日志记录组
件内。
(3 )Supports ,如果某个EJB 组件使用了Supports
事务属性,则只有调用它的客户已经启用了事务时,这一EJB
组件才会运行在事务中。如果客户并没有运行在事务中,则EJB
组建也不会运行在事务中。Supports 同Required
事务属性很相似,但是,Required 要求EJB
组件必须运行在事务中。如果使用Support
事务属性,EJB 组建很可嫩没有运行在事务中。
(4 )Mandatory ,Mandatory 事务属性要求调用EJB
组件的客户必须已经运行在事务中。如果从非事务性客户端调用使用Mandatory
属性的EJB
方法,那么客户将接受到系统抛出的javax.ejb.EJBTransactionRequiredException
异常。EJB 组件使用Mandatory
事务属性是非常安全的,它能够保证EJB
组建运行在事务中。如果客户没有运行在事务中,则不能够调用到应用了Mandatory
事务属性的EJB 组件。但是,Mandatory
事务属性要求第3 方(及客户)在调用EJB
组件前必须启动了事务。EJB 容器并不会为Mandatory
事务属性自动启动新事务,这是同Support
事务属性的最主要区别。
(5 )NotSupported ,如果EJB 组件使用了NotSupport
事务属性,它根本不会参与到事务中。如果调用者使用相关联的事务调用方法,容器就会暂停事务,调用方法,然后再方法返回时恢复事务。通常,此属性只用于非
实物性的自动确认模式中,支持JMS 提供者的MDB
。
(6 )Never ,如果EJB 组件使用Never
事务属性,它就不能够参与到事务中,而且,如果调用它的客户已经处于事务中,则容器会将javax.ejb.EJBException
异常抛给客户。
事务效果图,其中,T1 和T2 是2 个不同的事务,T1
是客户请求传递的事务,T2
是容器启动的事务,通过下表,能够理解各种事务属性在影响事务长度和范围方面所起的重要作用。
事务属性
客户事务
EJB 组件事务
使用CMT 实现Transaction :
view plaincopy to clipboardprint?
import
javax.annotation.Resource;
import
javax.ejb.SessionContext;
import
javax.ejb.Stateless;
import
javax.ejb.TransactionManagement;
import
javax.ejb.TransactionManagementType;
import
javax.ejb.TransactionAttribute;
import
javax.ejb.TransactionAttributeType;
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class OrderManagerBean
{
@Resource
private SessionContext
context;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void placeSnagItOrder(Item item, Customer customer)
{
try{
if(bidsExisting(item)) {
validateCredit(customer);
chargeCustomer(customer,
item);
removeItemFromBidding(item);
}
} catch(Exception e) {
context.setRollbackOnly();
}
}
}
CMT 的最大优势也是其最大弱点是,使用CMT
,会限制你将事务边界设置在业务方法开始和结束的位置,依靠容器决定何时开始、提交和回滚事务。另一方面,BMT
允许你通过变成确切指定这些细节,使用与JDBC
事务模型类似的语义。
例子:
view plaincopy to clipboardprint?
import
javax.annotation.Resource;
import
javax.ejb.SessionContext;
import
javax.ejb.Stateless;
import
javax.ejb.TransactionManagement;
import
javax.ejb.TransactionManagementType;
import
javax.transaction.UserTransaction;
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class OrderManagerBean
{
@Resource
private SessionContext
context;
public void placeSnagItOrder(Item item, Customer customer)
{
UserTransaction userTransaction =
context.getUserTransaction();
try{
userTransaction.begin();
if(!bidsExisting(item)) {
validateCredit(customer);
chargeCustomer(customer,
item);
removeItemFromBidding(item);
}
userTransaction.commit();
} catch (Exception e) {
userTransaction.rollback();
e.printStackTrace();
}
}
}
容器管理事务(Container-Managed Transaction, CMT
):容器管理事务允许组件自动征集(enlist
)到事务中,也就是说,EJB
组件从不需要显式地给出begin 、commit 、abort
语句,EJB 容器会替开发者考虑这些内容。EJB
容器会依据EJB
组件提供者指定的事务行为来界定相应的事务边界。在使用容器管理事务时,EJB
容器会拦截客户请求,并自动为EJB
组建启动新的事务,也就是说,容器会通过begin
语句调用底层事务系统,从而启动事务。随后,容器会将业务请求委派给EJB
组件,组件中的业务操作将运行在这一事务中。处于事务中的EJB
组件能够执行任何业务逻辑,如写入数据库、发送异步信息、调用其他的EJB
组件等。一旦在处理业务过程中出现问题,则EJB
组建需要通知EJB 容器去回滚事务。当EJB
组建完成业务处理后,会将控制权交回给EJB
容器。随后,EJB 容器能够通过commit 或abort
语句调用底层事务系统。
通过使用@TransactionAttribute
注释或部署描述符,开发者能够指定事务属性。EJB
容器通过分析事务属性便能够知道如何处理EJB
组件的事务需求。EJB 事务属性的取值有:
(1 )Required ,如果EJB
组件必须总是运行在事务中,则应该使用Required
模式。如果已经有事务在运行,则EJB
组件参与其中;如果没有事务运行,则EJB
容器会为EJB 组件启动新的事务。
Required
是默认和最常使用的事务属性值。这个值指定必须在事务之内调用EJB
方法。如果从非事务性客户端调用方法,那么容器会在调用方法之前开始事务,并且在方法返回时结束事务。另一方面,如果调用者从事务性上下文调用方法,那么
方法会联结已有事务。在从客户段传播事务的情况下,如果我们的方法表示应该回滚事务,那么容器不仅回回滚整个事务,而且会向客户端抛出异常,从而让客户端
知道它开始的事务已经被另一个方法回滚了。
(2 )Requires_New ,当客户调用EJB
时,如果总是希望启动新的事务,则应该使用RequiresNew
事务属性,如果客户在调用EJB
组件时已经存在事务,则当前事务会被挂起,进而容器启动新的事务,并将调用请求委派给EJB
组件。也就是说,如果客户端已经有了事务,那么它暂停该事务,知道方法返回位置,新事务是成功还是失败都不会影响客户端已有的事务。EJB
组件执行相应的业务操作,容器会提交或回滚事务,最终容器将恢复原有的事务,当然,如果客户在调用EJB
组件时不存在事务,则不需要执行事务的挂起或恢复操作。
RequiresNew 事务属性非常有用。如果EJB
组件需要事务的ACID 属性,并且将EJB
组件运行在单个独立的工作单元中,从而不会将其他外部逻辑也包括在当前的事务中,则必须使用RequiredNew
事务属性。如果需要事务,但是不希望事务的回滚影响客户端,就应该使用它。另外,当不希望客户端的回滚影响你的时候,也应该使用这个值。日志记录是个很好
的例子,即使父事务回滚,你也希望把错误情况记录到日志中,另一方面,日志记录细小调试信息的失败不应该导致回滚整个事务,并且问题应该仅限于日志记录组
件内。
(3 )Supports ,如果某个EJB 组件使用了Supports
事务属性,则只有调用它的客户已经启用了事务时,这一EJB
组件才会运行在事务中。如果客户并没有运行在事务中,则EJB
组建也不会运行在事务中。Supports 同Required
事务属性很相似,但是,Required 要求EJB
组件必须运行在事务中。如果使用Support
事务属性,EJB 组建很可嫩没有运行在事务中。
(4 )Mandatory ,Mandatory 事务属性要求调用EJB
组件的客户必须已经运行在事务中。如果从非事务性客户端调用使用Mandatory
属性的EJB
方法,那么客户将接受到系统抛出的javax.ejb.EJBTransactionRequiredException
异常。EJB 组件使用Mandatory
事务属性是非常安全的,它能够保证EJB
组建运行在事务中。如果客户没有运行在事务中,则不能够调用到应用了Mandatory
事务属性的EJB 组件。但是,Mandatory
事务属性要求第3 方(及客户)在调用EJB
组件前必须启动了事务。EJB 容器并不会为Mandatory
事务属性自动启动新事务,这是同Support
事务属性的最主要区别。
(5 )NotSupported ,如果EJB 组件使用了NotSupport
事务属性,它根本不会参与到事务中。如果调用者使用相关联的事务调用方法,容器就会暂停事务,调用方法,然后再方法返回时恢复事务。通常,此属性只用于非
实物性的自动确认模式中,支持JMS 提供者的MDB
。
(6 )Never ,如果EJB 组件使用Never
事务属性,它就不能够参与到事务中,而且,如果调用它的客户已经处于事务中,则容器会将javax.ejb.EJBException
异常抛给客户。
事务效果图,其中,T1 和T2 是2 个不同的事务,T1
是客户请求传递的事务,T2
是容器启动的事务,通过下表,能够理解各种事务属性在影响事务长度和范围方面所起的重要作用。
事务属性
客户事务
EJB 组件事务
事务属性 | 客户事务 | EJB 组件事务 |
Required | 无 T1 | T2 T1 |
RequiresNew | 无 T1 | T2 T2 |
Supports | 无 T1 | 无 T1 |
Mandatory | 无 T1 | 错误 T1 |
NotSupported | 无 T1 | 无 无 |
Never | 无 T1 | 无 错误 |
view plaincopy to clipboardprint?
import
javax.annotation.Resource;
import
javax.ejb.SessionContext;
import
javax.ejb.Stateless;
import
javax.ejb.TransactionManagement;
import
javax.ejb.TransactionManagementType;
import
javax.ejb.TransactionAttribute;
import
javax.ejb.TransactionAttributeType;
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class OrderManagerBean
{
@Resource
private SessionContext
context;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void placeSnagItOrder(Item item, Customer customer)
{
try{
if(bidsExisting(item)) {
validateCredit(customer);
chargeCustomer(customer,
item);
removeItemFromBidding(item);
}
} catch(Exception e) {
context.setRollbackOnly();
}
}
}
CMT 的最大优势也是其最大弱点是,使用CMT
,会限制你将事务边界设置在业务方法开始和结束的位置,依靠容器决定何时开始、提交和回滚事务。另一方面,BMT
允许你通过变成确切指定这些细节,使用与JDBC
事务模型类似的语义。
例子:
view plaincopy to clipboardprint?
import
javax.annotation.Resource;
import
javax.ejb.SessionContext;
import
javax.ejb.Stateless;
import
javax.ejb.TransactionManagement;
import
javax.ejb.TransactionManagementType;
import
javax.transaction.UserTransaction;
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class OrderManagerBean
{
@Resource
private SessionContext
context;
public void placeSnagItOrder(Item item, Customer customer)
{
UserTransaction userTransaction =
context.getUserTransaction();
try{
userTransaction.begin();
if(!bidsExisting(item)) {
validateCredit(customer);
chargeCustomer(customer,
item);
removeItemFromBidding(item);
}
userTransaction.commit();
} catch (Exception e) {
userTransaction.rollback();
e.printStackTrace();
}
}
}
相关文章推荐
- EJB 3事务之容器管理事务(CMT)BEAN管理事务
- EJB 3事务之容器管理事务(CMT)
- EJB 3事务之:容器管理事务(CMT)
- EJB 3事务之容器管理事务(CMT)
- EJB容器管理事务-提交和回滚
- EJB容器管理事务-提交和回滚
- CMT(容器管理事务)
- 【蛙蛙王子】CMT DEMO(容器管理事务演示)
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(一)——事务基本概念
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(二)——声明式事务
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(一)——事务基本概念
- spring 事务管理
- 全面分析 Spring 的编程式事务管理…
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(三)——编程式事务管理
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(二)——声明式事务
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(四)——参考网址
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(三)——编程式事务管理
- 全面分析EJB编程式事务管理(bmt)和声明式事务管理(cmt)(四)——参考网址
- glassfish3下报错"只有事务类型为 JTA 的持久性单元才能用作容器管理的实体管理器"
- 对于jboss EJB容器管理事务的问题