JTA可以在多个数据库上使用一个事务,weblogic等应用服务器提供了jta数据源的支持,可以直接被使用。但是tomcat本身并不支持这种特性。如果想在tomcat上使用jta就必须使用其它的工具。jotm就是一个独立的可以提供JTA功能的组件。
jotm有2中使用方式,1、结合容器的JNDI数据源提供JTA功能。2、使用jotm建立本地数据源。下面的内容是对第一种使用方式配置过程。
测试环境:
Tomcat 6.0.18
MySQL 5.1.47
Jotm 2.0.10
Spring 3.0.0 RC3
Hibernate 3.1.3
1:添加jotm jar
将jotm jar文件、数据库jdbc驱动以及相关的类库放到%catalina_home%/lib
commons-logging.jar
log4j.jar
commons-cli-1.0.jar
connector-1_5.jar
howl.jar
jotm.jar
jotm_iiop_stubs.jar
jotm_jrmp_stubs.jar
jta-spec1_0_1.jar
jts1_0.jar
objectweb-datasource.jar
ow_carol.jar
xapool.jar
注意:
1:common-logging.jar 和log4j.jar 也需要拷贝过来,并确保具体的应用下不能包含这2个文件。
2:应用程序中不能包含jta.jar,此文件与tomcat公共类路径下的jta-spec1_0_1.jar冲突。
3:%catalina_home%/lib是tomcat的公共类路径,jar、.class或.properties的文件都可以放在此目录下,可以被所有应用访问。
2:建立carol.properties配置文件
建立carol.properties,并放在%catalina_home%/lib下(放在这个目录下的jar或类文件可以被所有应用程序所访问)。 #JNDI调用协议 #本地RMI调用,必需设置成false,否则程序运行时会产生异常 #不使用CAROL的JNDI封装器 #不启用命名服务器 #命名工厂类 |
注意:
carol.jvm.rmi.local.call 必需设置成false,否则在运行时会报如下错误:
java.lang.NoSuchMethodError: sun.rmi.transport.ObjectTable.getStub(Ljava/rmi/Remote;)Ljava/rmi/server/RemoteStub
3:配置JNDI数据源
3.1在%catalina_home%/conf/context.xml的<Context></Context>标签内加入如下内容
<!—数据源1-->
<Resource name="jdbc/edit" auth="Container" type="javax.sql.DataSource"
factory="org.objectweb.jndi.DataSourceFactory"
driverClassName="com.p6spy.engine.spy.P6SpyDriver" username="root"
password="007" url="jdbc:mysql://localhost:3306/edit"/>
<!—数据源2 -->
<Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"
factory="org.objectweb.jndi.DataSourceFactory"
driverClassName="org.gjt.mm.mysql.Driver" username="root"
password="007" url="jdbc:mysql://localhost:3306/test"/>
<!—UserTransaction -->
<Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
注意:factory="org.objectweb.jndi.DataSourceFactory"指定创建数据源的工厂,如果省略这行数据源仍然可以被创建出来,但创建的是tomcat6提供的数据源,而不是jotm的数据源实现,是不能满足jta的事务的。
3.2引用全局数据源,在应用程序的META-INF下建立context.xml,文件内容如下
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<ResourceLink global="jdbc/edit" name="jdbc/edit" type="javax.sql.DataSource"/>
<ResourceLink global="jdbc/test" name="jdbc/test" type="javax.sql.DataSource"/>
<!-- ResourceLink name="UserTransaction" global="UserTransaction" type="javax.transaction.UserTransaction"/-->
</Context>
4:配置spring数据源
<?xml version="1.0" encoding="UTF-8"?>
<!-- =================================================================================================-->
<!-- -->
<!-- 数据源 -->
<!--使用aotm实现的jta事务,多数据源 -->
<!-- =================================================================================================-->
<beans xmlns=" http://www.springframework.org/schema/beans"
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx=" http://www.springframework.org/schema/tx"
xmlns:jee=" http://www.springframework.org/schema/jee"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd" >
<!-- 属性加载器 -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:spring/config.properties"/>
</bean>
<!-- 查找数据源 -->
<jee:jndi-lookup id="ds_edit" jndi-name="java:comp/env/jdbc/edit" />
<jee:jndi-lookup id="ds_test" jndi-name="java:comp/env/jdbc/test" />
<!-- jee:jndi-lookup id="userTransaction" jndi-name="UserTransaction" /-->
<!-- jta 事务管理器 -->
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
<!-- tx:annotation-driven transaction-manager="txManager" /-->
<!-- 【自动事务代理】使用的拦截器 -->
<bean id="serviceTransactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="txManager"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED,-Exception</prop>
</props>
</property>
</bean>
<!-- 【自动事务代理】创建器,使所有*Service业务Bean变成事务Bean -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<value>*Service</value>
</property>
<property name="interceptorNames">
<list>
<value>serviceTransactionInterceptor</value>
</list>
</property>
</bean>
<!-- HIBERNATE工厂 -->
<bean id="sessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="ds_edit" /></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/aisidi/edit/entity/hbm/Dog.hbm.xml</value>
</list>
</property>
</bean>
<!-- HIBERNATE工厂2 -->
<bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="ds_test" /></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/aisidi/edit/entity/hbm/Cat.hbm.xml</value>
</list>
</property>
</bean>