全局事务和局部最优 全局最优事务混合,求教解决方案

全局事务和局部事务混合,求教解决方案?
项目用的Spring+Mybatis项目开始时,是有多个局部事务的对应到serviceA中的方法a1,a2,对应数据源A,
serviceB中的方法b1,b2,对应数据源B,现在有新的需求,希望可以通过全局事务,实现对A,B的管理,用到的service方法有a1,b1。查阅资料得到的解决方案是atomikos + jta,实践发现也确实可行。但随之而来的问题是:a1,b1本身存在局部事务,如果再使用全局事务将二者统一管理即在函数C中调用a1,b1,需要修改a1,a2对应的transactionManager和其中使用的Mapper对应的数据源。会对原有代码做较多的更改。所以想请教一下,有没有什么合适的解决方案,在正常使用局部事务的同时,比较灵活方便的加入全局事务,并且可以尽量少的修改原有代码。多谢!
按时间排序
全局事务用spring的事务管理器,局部用动态代理或者配置aop?
你的问题是,你对事务隔离和分布式事务的理论一无所知。。。所以我觉得都没法给你解释,因为这本来根本就不是问题。。。不过我觉得你还算是认真思考了的,所以我试着给你简单的整理一下,如果看不懂呢,就自行google就好了。首先,我们考虑事务隔离,为了让你的思路简单起见,我们假设你的两个service是同一个数据源,这样一来,我们就只需要考虑事务隔离的问题了,这个我不打算展开,因为对同数据源下如何隔离事务,spring的文档有详细的说明,你只需要照着做就行了。最后强调一点,最好先进行理论学习,理解什么叫事务隔离。然后,我们考虑多个数据源的情况下,这个时候,我们需要用到JTA来做分布式事务的二阶段提交,这个本身也很复杂,还是同样的建议,先进行理论学习,理解了分布式事务的二阶段提交的概念之后,再去看spring的文档,同样,spring的文档对配置JTA完成分布式事务也有详细的说明,同样,照着做就行了。你看,这是不是非常简单,事务隔离和分布式事务本身还是两件事情,你把他们搅在一起,你就会觉得没法下手,但我能够告诉你的是,他们是两件无关的事情,你只主要分别把他们按照文档配置好就行了。最后呢,补充一个进阶点的内容,前提是你对上面的两个问题都已经充分的理解之后,你可以去搜索一下「Best Efforts 1PC」这个关键字,实际上,如果使用这种模式的话,就用不到JTA了,只需要配置好事务隔离,spring的AOP事务模式本身就已经是「Best Efforts 1PC」的了,嗯,我经手过的项目,一般都是这样做的。至于「Best Efforts 1PC」和基于JTA的两阶段提交,究竟那个能够满足你的要求,他们的优劣比较,取决于你自己的业务逻辑和需求,同样的,你需要自行研究并作出判断。
已有帐号?
社交帐号登录
无法登录?
社交帐号登录第&7&章&事务管理
第&7&章&事务管理7.1.&Spring事务抽象Spring提供了一致的事务管理抽象。这个抽象是Spring最重要的抽象之一,
它有如下的优点:为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、iBATIS数据库层
和JDO提供比大多数事务API更简单的,易于使用的编程式事务管理API整合Spring数据访问抽象支持Spring声明式事务管理传统上,J2EE开发者有两个事务管理的选择: 全局事务或
局部事务。全局事务由应用服务器管理,使用JTA。局部
事务是和资源相关的:例如,一个和JDBC连接关联的事务。这个选择有深刻的含义。
全局事务可以用于多个事务性的资源(需要指出的是多数应用使用单一事务性
的资源)。使用局部事务,应用服务器不需要参与事务管理,并且不能帮助确保
跨越多个资源的事务的正确性。全局事务有一个显著的不利方面,代码需要使用JTA:一个笨重的API(部分是
因为它的异常模型)。此外,JTA的UserTransaction通常需
要从JNDI获得,这意味着我为了JTA需要同时使用JNDI和JTA。
显然全部使用全局事务限制了应用代码的重用性,因为JTA通常只在应用服
务器的环境中才能使用。使用全局事务的比较好的方法是通过EJB的CMT
(容器管理的事务):
声明式事务管理的一种形式(区别于编程式事务管理
)。EJB的CMT不需要任何和事务相关的JNDI查找,虽然使用EJB本身
肯定需要使用JNDI。它消除大多数——不是全部——书写Java代码控制事务的需求。
显著的缺点是CMT绑定在JTA和应用服务器环境上,并且只有我们选择
使用EJB实现业务逻辑,或者至少处于一个事务化EJB的外观(Facade)后
才能使用它。EJB有如此多的诟病,当存在其它声明式事务管理时,
EJB不是一个吸引人的建议。局部事务容易使用,但也有明显的缺点:它们不能用于多个事务性资
源,并且趋向侵入的编程模型。例如,使用JDBC连接事务管理的代码不能用于
全局的JTA事务中。Spring解决了这些问题。它使应用开发者能够使用在任何环境
下使用一致的编程模型。你可以只写一次你的代码,这在不同环境
下的不同事务管理策略中很有益处。Spring同时提供声明式和编程式事务管理。使用编程式事务管理,开发者直接使用Spring事务抽象,这个抽象可以使用在任何
底层事务基础之上。使用首选的声明式模型,开发者通常书写很少的事务相关代
码,因此不依赖Spring或任何其他事务API。7.2.&事务策略Spring事务抽象的关键是事务策略的概念。这个概念由
org.springframework.transaction.PlatformTransactionManager
接口体现,如下:
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionE
void commit(TransactionStatus status) throws TransactionE
void rollback(TransactionStatus status) throws TransactionE
}这首先是一个SPI接口,虽然它也可以在编码中使用。注意按照Spring的哲学,
这是一个接口。因而如果需要它可以很容易地被模拟和
桩化。它也没有和一个查找策略如JNDI捆绑在一起:PlatformTransactionManager
的实现定义和其他Spring IoC容器中的对象一样。这个好处使得即使使用JTA,也
是一个很有价值的抽象:事务代码可以比直接使用JTA更加容易测试。继续Spring哲学,TransactionException是unchecked的。
低层的事务失败几乎都是致命。很少情况下应用程序代码可以从它们
中恢复,不过应用开发者依然可以捕获并处理
TransactionException。getTransaction()根据一个类型为
TransactionDefinition的参数返回一个
TransactionStatus对象。返回的
TransactionStatus对象可能代表一个新的或已经存在的事
务(如果在当前调用堆栈有一个符合条件的事务)。如同J2EE事务上下文一样,一个TransactionStatus也是和执
行的线程关联的。TransactionDefinition接口指定:事务隔离:当前事务和其它事务的隔离的程度。
例如,这个事务能否看到其他事务未提交的写数据?事务传播:通常在一个事务中执行的
所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在,
有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的
事务中运行(大多数情况);或者挂起现有事务,创建一个新的事务。
Spring提供EJB CMT中熟悉的事务传播选项。事务超时: 事务在超时前能运行多
久(自动被底层的事务基础设施回滚)。只读状态: 只读事务不修改任何数
据。只读事务在某些情况下(例如当使用Hibernate时)可可是一种非常有用的优化。
这些设置反映了标准概念。如果需要,请查阅讨论事务隔离层次和其他核心事
务概念的资源:理解这些概念在使用Spring和其他事务管理解决方案时是非常关键的。
TransactionStatus接口为处理事务的代码提供一个简单
的控制事务执行和查询事务状态的方法。这个概念应该是熟悉的,因为它们在所
有的事务API中是相同的:public interface TransactionStatus {
boolean isNewTransaction();
void setRollbackOnly();
boolean isRollbackOnly();
}但是使用Spring事务管理时,定义
PlatformTransactionManager的实现是基本方式。在好的Spring
风格中,这个重要定义使用IoC实现。PlatformTransactionManager实现通常需要了解它们工作
的环境:JDBC、JTA、Hibernate等等。下面来自Spring范例jPetstore中的
dataAccessContext-local.xml,它展示了一个局部
PlatformTransactionManager实现是如何定义的。它将和JDBC一起工作。我们必须定义JDBC数据源,然后使用DataSourceTransactionManager,提供给
它的一个数据源引用。&bean id="dataSource"
class="mons.dbcp.BasicDataSource" destroy-method="close"&
&property name="driverClassName"&&value&${jdbc.driverClassName}&/value&&/property&
&property name="url"&&value&${jdbc.url}&/value&&/property&
&property name="username"&&value&${jdbc.username}&/value&&/property&
&property name="password"&&value&${jdbc.password}&/value&&/property&
&/bean&PlatformTransactionManager定义如下:&bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&
&property name="dataSource"&&ref local="dataSource"/&&/property&
&/bean&如果我们使用JTA,如同范例中dataAccessContext-jta.xml,
我们需要使用通过JNDI获得的容器数据源,和一个JtaTransactionManager实
现。JtaTransactionManager不需要知道数据源,或任何其他特定资源,因为它将
使用容器的全局事务管理。&bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&
&property name="jndiName"&&value&jdbc/jpetstore&/value&&/property&
&bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/&
我们可以很容易地使用Hibernate局部事务,如同下面Spring的PetClinic
示例应用中的例子的一样。在这种情况下,我们需要定义一个Hibernate的LocalSessionFactory,应用程
序将使用它获得Hibernate的会话。数据源bean定义和上面例子类似,这里不再罗列(如果这是容器数据源,它应该是非事务的,因为Spring会管理事务,
而不是容器)。这种情况下,“transactionManager” bean的类型是HibernateTransactionManager。
和DataSourceTransactionManager拥有一个数据源的引用一样,
HibernateTransactionManager需要一个SessionFactory的引用。&bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"&
&property name="dataSource"&&ref local="dataSource"/&&/property&
&property name="mappingResources"&
&value&org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml&/value&
&/property&
&property name="hibernateProperties"&
&prop key="hibernate.dialect"&${hibernate.dialect}&/prop&
&/property&
&bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager"&
&property name="sessionFactory"&&ref local="sessionFactory"/&&/property&
&/bean&使用Hibernate和JTA事务,我们可以简单地使用JtaTransactionManager,
就象JDBC或任何其他资源策略一样。&bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/&注意任何资源的JTA配置都是这样的,因为它们都是全局事务。在所有这些情况下,应用程序代码不需要任何更改。我们可以仅仅更改配置
来更改管理事务的方式,即使这些更改意味这从局部事务转换到全局事务或者相反
的转换。如果不使用全局事务,你需要采用一个特定的编码规范。幸运的是它非常简单
。你需要以一个特殊的方式获得连接资源或者会话资源,允许相关的
PlatformTransactionManager实现跟踪连接的使用,并且当需要时应用事务管理。例如,如果使用JDBC,你不应该调用一个数据源的
getConnection()方法,而必须使用Spring的
org.springframework.jdbc.datasource.DataSourceUtils类,如下:Connection conn = DataSourceUtils.getConnection(dataSource);这将提供额外的好处,任何SQLException都被Spring的
CannotGetJdbcConnectionException封装起来,它属于Spring的unchecked
的DataAccessException的类层次。这给你比
简单地从SQLException获得更多的信息,并且确保跨数据
库,甚至跨越不同持久化技术的可移植性。没有Spring事务管理的情况下,这也能很好地工作,因此无论使用
Spring事务管理与否,你都可以使用它。当然,一旦你使用Spring的JDBC支持或Hibernate支持,你将不想使用
DataSourceUtils或其他帮助类,因为与直接使用相关API相比,你将更乐意使用Spring的抽象。
例如,如果你使用Spring的JdbcTemplate或jdbc.object包来简化使用JDBC,
正确的数据库连接将自动取得,你不需要书写任何特殊代码。7.3.&编程式事务管理Spring提供两种方式的编程式事务管理使用TransactionTemplate直接使用一个PlatformTransactionManager实现我们通常推荐使用第一种方式。第二种方式类似使用JTA UserTransaction API
(虽然异常处理少一点麻烦)。7.3.1.&使用TransactionTemplateTransactionTemplate采用和其他Spring模板
,如JdbcTemplate和
HibernateTemplate,一样的方法。它使用回调方法,把应用
程序代码从处理取得和释放资源中解脱出来(不再有try/catch/finally)。如同
其他模板,TransactionTemplate是线程安全的。必须在事务上下文中执行的应用代码看起来像这样,注意使用
TransactionCallback可以返回一个值:Object result = tt.execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
updateOperation1();
return resultOfUpdateOperation2();
});如果没有返回值,使用TransactionCallbackWithoutResult,
如下:tt.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
updateOperation1();
updateOperation2();
});回调中的代码可以调用TransactionStatus对象的
setRollbackOnly()方法来回滚事务。想要使用TransactionTemplate的应用类必须能访问一
个PlatformTransactionManager:通常通过一个JavaBean属
性或构造函数参数暴露出来。使用模拟或桩化的PlatformTransactionManager,单元测试
这些类很简单。没有JNDI查找和静态魔术代码:它只是一个简单的接口。和平常一样,
你可以使用Spring简化单元测试。7.3.2.&使用PlatformTransactionManager你也可以使用
org.springframework.transaction.PlatformTransactionManager
直接管理事务。简单地通过一个bean引用给你的bean传递一个你使用的
PlatformTransactionManager实现。然后,
使用TransactionDefinition和
TransactionStatus对象就可以发起事务,回滚和提交。
DefaultTransactionDefinition def = new DefaultTransactionDefinition()
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransactionDefinition(def);
// execute your business logic here
} catch (MyException ex) {
transactionManager.rollback(status);
mit(status);7.4.&声明式事务管理Spring也提供了声明式事务管理。这是通过Spring AOP实现的。大多数Spring用户选择声明式事务管理。这是最少影响应用代码的选择,
因而这是和非侵入性的轻量级容器的观念是一致的。
从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。
它们的基本方法是相似的:都可以指定事务管理到单独的方法;如果需要可以在事务上
下文调用setRollbackOnly()方法。不同之处如下:不象EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。
只需更改配置文件,它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作
Spring可以使声明式事务管理应用到普通Java对象,不仅仅是特殊的类,如EJBSpring提供声明式回滚规则:EJB没有对应的特性,
我们将在下面讨论这个特性。回滚可以声明式控制,不仅仅是编程式的
Spring允许你通过AOP定制事务行为。例如,如果需要,你可以在事务
回滚中插入定制的行为。你也可以增加任意的通知,就象事务通知一样。使用
EJB CMT,除了使用setRollbackOnly(),你没有办法能
够影响容器的事务管理Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。如
果你需要这些特性,我们推荐你使用EJB。然而,不要轻易使用这些特性。通常我
们并不希望事务跨越远程调用回滚规则的概念是很重要的:它们使得我们可以指定哪些异常应该发起自
动回滚。我们在配置文件中,而不是Java代码中,以声明的方式指定。因此,虽然我们仍
然可以编程调用TransactionStatus对象的
setRollbackOnly()方法来回滚当前事务,多数时候我们可以
指定规则,如MyApplicationException应该导致回滚。
这有显著的优点,业务对象不需要依赖事务基础设施。例如,它们通常不需要引
入任何Spring API,事务或其他任何东西。EJB的默认行为是遇到系统异常(通常是运行时异常),
EJB容器自动回滚事务。EJB CMT遇到应用程序异常
(除了java.rmi.RemoteException外的checked异常)时不
会自动回滚事务。虽然Spring声明式事务管理沿用EJB的约定(遇到unchecked
异常自动回滚事务),但是这是可以定制的。按照我们的测试,Spring声明式事务管理的性能要胜过EJB CMT。通常通过TransactionProxyFactoryBean设置Spring事务代理。我们需
要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我
们定义TransactionProxyFactoryBean时,必须提供一个相关的
PlatformTransactionManager的引用和事务属性。
事务属性含有上面描述的事务定义。&bean id="petStore"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&
&property name="transactionManager"&&ref bean="transactionManager"/&&/property&
&property name="target"&&ref bean="petStoreTarget"/&&/property&
&property name="transactionAttributes"&
&prop key="insert*"&PROPAGATION_REQUIRED,-MyCheckedException&/prop&
&prop key="update*"&PROPAGATION_REQUIRED&/prop&
&prop key="*"&PROPAGATION_REQUIRED,readOnly&/prop&
&/property&
&/bean&事务代理会实现目标对象的接口:这里是id为petStoreTarget的bean。(使用
CGLIB也可以实现具体类的代理。只要设置proxyTargetClass属性为true就可以。
如果目标对象没有实现任何接口,这将自动设置该属性为true。通常,我们希望面向接口而不是
类编程。)使用proxyInterfaces属性来限定事务代理来代
理指定接口也是可以的(一般来说是个好想法)。也可以通过从
org.springframework.aop.framework.ProxyConfig继承或所有AOP代理工厂共享
的属性来定制TransactionProxyFactoryBean的行为。
这里的transactionAttributes属性定义在
org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource
中的属性格式来设置。这个包括通配符的方法名称映射是很直观的。注意
insert*的映射的值包括回滚规则。添加的-MyCheckedException
指定如果方法抛出MyCheckedException或它的子类,事务将
会自动回滚。可以用逗号分隔定义多个回滚规则。-前缀强制回滚,+前缀指定提
交(这允许即使抛出unchecked异常时也可以提交事务,当然你自己要明白自己
在做什么)。TransactionProxyFactoryBean允许你通过
“preInterceptors”和“postInterceptors”属性设置“前”或“后”通知来提供额外的
拦截行为。可以设置任意数量的“前”和“后”通知,它们的类型可以是
Advisor(可以包含一个切入点),
MethodInterceptor或被当前Spring配置支持的通知类型
(例如ThrowAdvice,
AfterReturningtAdvice或BeforeAdvice,
这些都是默认支持的)。这些通知必须支持实例共享模式。如果你需要高级AOP特
性来使用事务,如有状态的maxin,那最好使用通用的
org.springframework.aop.framework.ProxyFactoryBean,
而不是TransactionProxyFactoryBean实用代理创建者。也可以设置自动代理:配置AOP框架,不需要单独的代理定义类就可以生成类的
代理。更多信息和实例请参阅AOP章节。无论你是是否是AOP专家,都可以更有效地使用Spring的
声明式事务管理。但是,如果你想成为Spring AOP的高级用户,你会发现整合声明
式事务管理和强大的AOP性能是非常容易的。7.4.1.&BeanNameAutoProxyCreator,另一种声明方式TransactionProxyFactoryBean非常有用,当事
务代理包装对象时,它使你可以完全控制代理。如果你需要用一致的方式(例如,一个
样板文件,“使所有的方法事务化”)包装大量的bean,使用一个
BeanFactoryPostProcessor的一个实现,
BeanNameAutoProxyCreator,可以提供另外一种方法,
这个方法在这种简单的情况下更加简单。重述一下,一旦ApplicationContext读完它的初始化信息,它将初始化所有实
现BeanPostProcessor接口的bean,并且让它们后处理
ApplicationContext中所有其他的bean。所以使用这种机制,一个正
确配置的BeanNameAutoProxyCreator可以用来后处
理所有ApplicationContext中所有其他的bean(通过名称来识别),并且把它
们用事务代理包装起来。真正生成的事务代理和使用
TransactionProxyFactoryBean生成的基本一致,这里不再
讨论。让我们看下面的配置示例:
&!-- Transaction Interceptor set up to do PROPOGATION_REQUIRED on all methods --&
&bean id="matchAllWithPropReq"
class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource"&
&property name="transactionAttribute"&&value&PROPAGATION_REQUIRED&/value&&/property&
&bean id="matchAllTxInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor"&
&property name="transactionManager"&&ref bean="transactionManager"/&&/property&
&property name="transactionAttributeSource"&&ref bean="matchAllWithPropReq"/&&/property&
&!-- One BeanNameAutoProxyCreator handles all beans where we want all methods to use
PROPOGATION_REQUIRED --&
&bean id="autoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"&
&property name="interceptorNames"&
&idref local="matchAllTxInterceptor"/&
&idref bean="hibInterceptor"/&
&/property&
&property name="beanNames"&
&idref local="core-services-applicationControllerSevice"/&
&idref local="core-services-deviceService"/&
&idref local="core-services-authenticationService"/&
&idref local="core-services-packagingMessageHandler"/&
&idref local="core-services-sendEmail"/&
&idref local="core-services-userService"/&
&/property&
&/bean&假设我们在ApplicationContext中已经有一个TransactionManager的实例
,我们首先要做的使创建一个
TransactionInterceptor实例。
根据通过属性传递的TransactionAttributeSource接口的一个实现,
ransactionInterceptor决定哪个
方法被拦截。这个例子中,我们希望处理匹配
所有方法这种最简单的情况。这个不是最有效的方式,但设置非常迅速,因为
我可以使用预先定义的匹配所有方法的
MatchAlwaysTransactionAttributeSource类。如果我
们需要特定的方式,可以使用
MethodMapTransactionAttributeSource,
NameMatchTransactionAttributeSource或
AttributesTransactionAttributeSource。现在我们已经有了事务拦截器,我们只需把它交给我们定义的
BeanNameAutoProxyCreator实例中,这样AppliactonContext中
定义
bean以同样的方式被封装。你可以看到,这
比用TransactionProxyFactoryBean以一种方式单独封
bean简洁很
多。封装
bean只需添加一行配置。你也许注意到可以应用多个拦截器。在这个例子中,我们还应用了一个
前面定义的HibernateInterceptor
(bean id=hibInterceptor),它为我们管理
Hibernare的会话。有一件事值得注意,就是在TransactionProxyFactoryBean,
和BeanNameAutoProxyCreator切换时bean的命名。
第一种情况,你只需给你想要包装的bean一个类似myServiceTarget的id,
给代理对象一个类似myService的id,然后所有代理对象的用户只需引用代理对象,
如myService(这些是通用命名规范,
要点是目标对象要有和代理对象不同的名称,并且它们都要在ApplicationContext中可用)。然而,
使用BeanNameAutoProxyCreator时,
你得命名目标对象为myService。
然后当BeanNameAutoProxyCreator后处理目标对象
并生成代理时,它使得代理以和原始对象的名称被插入到
ApplicationContext中。从这一点看,只有代理(含有被包装的对象)在ApplicationContext中可用。7.5.&编程式还是声明式事务管理如果你只有很少的事务操作,使用编程式事务管理才是个好主意。例如,
如果你有一个WEB应用需要为某些更新操作提供事务,你可能不想用Spring或其
他技术设置一个事务代理。使用
TransactionTemplate可能是个很好的方法。另一方面,如果你的应用有大量的事务操作,声明式事务管理就很有价值。它使得事务管理从业务逻辑分离,
并且Spring中配置也不困难。使用Spring,而不是EJB CMT,声明式事务管理配置的成本极大地降低。7.6.&你需要应用服务器管理事务吗?Spring的事务管理能力--尤其声明式事务管理--极大地改变了J2EE应用程序需要
应用服务器的传统想法。尤其,你不需要应用服务器仅仅为了通过EJB声明事务。事实上,即使你拥
有强大JTA支持的应用服务器,你也可以决定使用Spring声明式事务管理提供比
EJB CMT更强大更高效的编程模型。只有需要支持多个事务资源时,你才需要应用服务器的JTA支持。许多应用没有
这个需求。例如许多高端应用使用单一的,具有高度扩展性的数据库,如Oracle 9i RAC。当然也许你需要应用服务器的其它功能,如JMS和JCA。但是如果你只需使用
JTA,你可以考虑开源的JTA实现,如JOTM(Spring整合了JOTM)。但是,
;早期,高端的应用服务器提供更健壮的XA资源支持。最重要一点,使用Spring,你可以选择何时将你的应用迁移到完整
应用服务器。使用EJB CMT或JTA都必须书写代码使用局部事务,
例如JDBC连接的事务,如果以前需要全局的容器管理的事务,还要面临着繁重
的改写代码的过程,这些日子一去不复返了。使用Spring只有配置需要改变,你的代码
不需要修改。
7.7.&公共问题开发着需要按照需求仔细的使用正确的
PlatformTransactionManager实现。
理解Spring事务抽象时如何和JTA全局事务一起工作是非常重要的。使用得当,
就不会有任何冲突:Spring仅仅提供一个简单的,可以移植的抽象层。如果你使用全局事务,你必须为你的所有事务操作使用Spring的
org.springframework.transaction.jta.JtaTransactionManager。
否则Spring将试图在象容器数据源这样的资源上执行局部事务。这样的局部事务没有任何
意义,好的应用服务器会把这作为一个错误。

我要回帖

更多关于 全局变量和局部变量 的文章

 

随机推荐