Jboss下使用spring配置实现JTA全局事务管理(下)

前言

上一篇初步简单实现事务管理,只是针对单数据源实现,对单数据源内的操作能够回滚。出现多个数据源,且多个数据源的操作出现在同一个service方法中时,不能实现多个数据源操作同时回滚,本篇将介绍简单实现jta全局事务。

JBoss下配置数据源

应用服务器下配置数据源,项目中通过jndi方式引入,这里以jboss为例,配置 standalone.xml ,设置数据源url,username,password,同时设置jndi name。如下:

     <datasources>
	<datasource jndi-name="java:jboss/datasources/ExampleDS"
		pool-name="ExampleDS" enabled="true" use-java-context="true">
		<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
		<driver>h2</driver>
		<security>
			<user-name>sa</user-name>
			<password>sa</password>
		</security>
	</datasource>
	<datasource jndi-name="java:/pocDS" pool-name="mysqlDS_bdpponldb_1"
		enabled="true" use-java-context="false">
		<connection-url>jdbc:mysql://IP1:port1/database1</connection-url>
		<driver>MYSQL</driver>
		<security>
			<security-domain>EncryptedPassword_**_1</security-domain>
		</security>
	</datasource>
	<drivers>
		<driver name="h2" module="com.h2database.h2">
			<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
		</driver>
		<driver name="MYSQL" module="com.mysql">
			<driver-class>com.mysql.jdbc.Driver</driver-class>
		</driver>
	</drivers>
	<datasource jndi-name="java:/jdbc/mgmdb" pool-name="mysqlDS_ccmgmdb_1"
		enabled="true" use-java-context="false">
		<connection-url> jdbc:mysql://IP2:port2/database2</connection-url>
		<driver>MYSQL</driver>
		<security>
			<security-domain>EncryptedPassword_**_1</security-domain>
		</security>
	</datasource>
	<datasource jndi-name="java:/jdbc/onldb     " pool-name="mysqlDS_cconldb_2"
		enabled="true" use-java-context="false">
		<connection-url> jdbc:mysql://IP3:port3/database3</connection-url>
		<driver>MYSQL</driver>
		<security>
			<security-domain>EncryptedPassword_**_2</security-domain>
		</security>
	</datasource>
	<datasource jndi-name="java:/jdbc/webdb    " pool-name="mysqlDS_ccwebdb_3"
		enabled="true" use-java-context="false">
		<connection-url> jdbc:mysql://IP4:port4/database4</connection-url>
		<driver>MYSQL</driver>
		<security>
			<security-domain>EncryptedPassword_ccwebdb_3</security-domain>
		</security>
	</datasource>
	<datasource jndi-name="java:/jdbc/webdbck" pool-name="mysqlDS_ccwebdb_4"
		enabled="true" use-java-context="false">
		<connection-url>jdbc:mysql://IP5:port5/database5</connection-url>
		<driver>MYSQL</driver>
		<security>
			<security-domain>EncryptedPassword_ccw***b_5</security-domain>
		</security>
	</datasource>
    </datasources> 


配置好多个datasource之后,在spring.xml中引入。如下:

		<?xml version="1.0" encoding="UTF-8"?>
		<beans xmlns="http://www.springframework.org/schema/beans"
			   xmlns:context="http://www.springframework.org/schema/context"
			   xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx"
			   xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			   xsi:schemaLocation="
				   http://www.springframework.org/schema/beans
				   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
				   http://www.springframework.org/schema/context
				   http://www.springframework.org/schema/context/spring-context-3.0.xsd
				   http://www.springframework.org/schema/task
				   http://www.springframework.org/schema/task/spring-task-3.0.xsd
				   http://www.springframework.org/schema/tx
				   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
				   http://www.springframework.org/schema/util
				   http://www.springframework.org/schema/util/spring-util-3.0.xsd">
			<!-- 管理库 -->
			<bean id="dataSourceMgm" class="org.springframework.jndi.JndiObjectFactoryBean">
				<property name="jndiName">
					<value>java:/jdbc/mgmdb</value>
				</property>
			</bean>
			
		  
			<bean id="sessionFactoryMgm"
				  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
				<property name="dataSource" ref="dataSourceMgm" />
				<property name="packagesToScan" value="com.packge.*" />
				<property name="hibernateProperties">
					<props>
						<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
						<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider
						</prop>
						<prop key="hibernate.connection.characterEncoding">utf-8</prop>
						<prop key="hibernate.connection.useUnicode">true</prop>
						<prop key="hibernate.show_sql">true</prop>
						<prop key="javax.persistence.validation.mode">none</prop>
					</props>
				</property>
			</bean>
			<bean id="transactionManagerMgm"
				  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
				<property name="sessionFactory" ref="sessionFactoryMgm" />
			</bean>
			<bean id="hibernateTemplateMgm" class="org.springframework.orm.hibernate3.HibernateTemplate">
				<property name="sessionFactory" ref="sessionFactoryMgm" />
			</bean>
			<bean id="jdbcTemplateMgm" class="org.springframework.jdbc.core.JdbcTemplate">
				<property name="dataSource" ref="dataSourceMgm" />
			</bean>
			<!-- 库2 -->
			<bean id="dataSourceOnl"  class="org.springframework.jndi.JndiObjectFactoryBean">
				<property name="jndiName">
					<value>java:/jdbc/onldb</value>
				</property>
			</bean>
			
			<bean id="sessionFactoryOnl"
				  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
				<property name="dataSource" ref="dataSourceOnl" />
				<property name="packagesToScan" value="com.packge.*" />
				<property name="hibernateProperties">
					<props>
						<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
						<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider
						</prop>
						<prop key="hibernate.connection.characterEncoding">utf-8</prop>
						<prop key="hibernate.connection.useUnicode">true</prop>
						<prop key="hibernate.show_sql">true</prop>
						<prop key="javax.persistence.validation.mode">none</prop>
					</props>
				</property>
			</bean>
			<bean id="transactionManagerOnl"
				  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
				<property name="sessionFactory" ref="sessionFactoryOnl" />
			</bean>
			<bean id="hibernateTemplateOnl" class="org.springframework.orm.hibernate3.HibernateTemplate">
				<property name="sessionFactory" ref="sessionFactoryOnl" />
			</bean>
			<bean id="jdbcTemplateOnl" class="org.springframework.jdbc.core.JdbcTemplate">
				<property name="dataSource" ref="dataSourceOnl" />
			</bean>
			<!--3库 -->
			<bean id="dataSourceWeb" class="org.springframework.jndi.JndiObjectFactoryBean">
				<property name="jndiName">
					<value>java:/jdbc/webdb</value>
				</property>
			</bean>
			
		   <!--  <bean id="dataSourceWeb" class="com.mchange.v2.c3p0.ComboPooledDataSource"
				destroy-method="close">
				<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
				<property name="jdbcUrl" value="jdbc:mysql://172.18.63.18:60004/ccwebdb"></property>
				<property name="user" value="cc_webdb"></property>
				<property name="password" value="cc_webdb"></property>
				<property name="maxPoolSize" value="200"></property>
				<property name="minPoolSize" value="50"></property>
			</bean> -->
			<bean id="sessionFactoryWeb"
				  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
				<property name="dataSource" ref="dataSourceWeb" />
				<property name="packagesToScan" value="com.packge.web.*" />
				<property name="hibernateProperties">
					<props>
						<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
						<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider
						</prop>
						<prop key="hibernate.connection.characterEncoding">utf-8</prop>
						<prop key="hibernate.connection.useUnicode">true</prop>
						<prop key="hibernate.show_sql">true</prop>
						<prop key="javax.persistence.validation.mode">none</prop>
					</props>
				</property>
			</bean>
			<bean id="transactionManagerWeb"
				  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
				<property name="sessionFactory" ref="sessionFactoryWeb" />
			</bean>
			<bean id="hibernateTemplateWeb" class="org.springframework.orm.hibernate3.HibernateTemplate">
				<property name="sessionFactory" ref="sessionFactoryWeb" />
			</bean>
			<bean id="jdbcTemplateWeb" class="org.springframework.jdbc.core.JdbcTemplate">
				<property name="dataSource" ref="dataSourceWeb" />
			</bean>
			<!-- 4库 -->
			<bean id="dataSourceWebdbck" class="org.springframework.jndi.JndiObjectFactoryBean">
				<property name="jndiName">
					<value>java:/jdbc/webdbck</value>
				</property>
			</bean>
			
			<!-- <bean id="dataSourceWebdbck" class="com.mchange.v2.c3p0.ComboPooledDataSource"
				destroy-method="close">
				<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
				<property name="jdbcUrl" value="jdbc:mysql://172.18.63.5:60002/ccwebdb"></property>
				<property name="user" value="cup_dba"></property>
				<property name="password" value="OStem@00"></property>
				<property name="maxPoolSize" value="200"></property>
				<property name="minPoolSize" value="50"></property>
			</bean> -->
			<bean id="sessionFactoryWebdbck"
				  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
				<property name="dataSource" ref="dataSourceWebdbck" />
				<property name="packagesToScan" value="com.packge.cc.ds.webdbck.*" />
				<property name="hibernateProperties">
					<props>
						<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
						<prop key="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider
						</prop>
						<prop key="hibernate.connection.characterEncoding">utf-8</prop>
						<prop key="hibernate.connection.useUnicode">true</prop>
						<prop key="hibernate.show_sql">true</prop>
						<prop key="javax.persistence.validation.mode">none</prop>
					</props>
				</property>
			</bean>
			<bean id="transactionManagerWebdbck"
				  class="org.springframework.orm.hibernate3.HibernateTransactionManager">
				<property name="sessionFactory" ref="sessionFactoryWebdbck" />
			</bean>
			<bean id="hibernateTemplateWebdbck" class="org.springframework.orm.hibernate3.HibernateTemplate">
				<property name="sessionFactory" ref="sessionFactoryWebdbck" />
			</bean>
			<bean id="jdbcTemplateWebdbck" class="org.springframework.jdbc.core.JdbcTemplate">
				<property name="dataSource" ref="dataSourceWebdbck" />
			</bean>

		</beans>


如果按上述配置之后,配置tx时,需要如下配置,否则会报错,找不到默认的 tansactionManager, 
    <tx:annotation-driven transaction-manager="transactionManagerMgm"/>
    <tx:annotation-driven transaction-manager="transactionManagerOnl"/>
    <tx:annotation-driven transaction-manager="transactionManagerWeb"/>
    <tx:annotation-driven transaction-manager="transactionManagerWebdbck"/>

这样配置之后,发现并没有jta的影子,因为还没有实现全局事务,上述依旧不能多数据源回滚。 需要在bean配置中,添加如下配置:

    <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

同时,tx配置需要改为:

    <tx:annotation-driven transaction-manager="jtaTransactionManager"/>
而不需要配置每个数据源的transactionManager。

JAVA代码中测试:

	@Autowired
	private TblCcmgmUsrInfDao userInfoDao;
	@Autowired
	private TblCcmgmMchntDao mchntInfDao;
	@Autowired
	private TblCcmgmRoleFunctionRelatedDao roleFunctionRelatedDao;
	@Autowired
	private TblCloudzdAcpBillInfoDao billDao;
	@Autowired
	private OnlBillInfDao onlBillDao;


	@Override
	public void updateUsrPwd(UserInfoDto dto) {
		TblCcmgmUsrInf usrInf = userInfoDao.get(dto.getUsrIded());
		usrInf.setUsrPwd(dto.getUsrPwd());
		usrInf.setRecUpdTs(new Timestamp(new Date().getTime()));
		usrInf.setRecUpdUsrId(dto.getCurrentUsrId());
		userInfoDao.modify(usrInf);
		logger.info("jta test");
		TblCloudzdAcpBillInfo inf = new TblCloudzdAcpBillInfo();
		inf.setType("q");
		billDao.save(inf);
		TblCconlBillInf billInf = new TblCconlBillInf();
		billInf.setBillDate("4688grsegsr654gserrggggggggggggggggggggggggggggggggggggggg");
		onlBillDao.save(billInf);
	}

最后一个因字段长度超限而插入失败,则前面所有数据操作均回滚。

最后

该实现未经过充分测试,还需要到具体项目中,测试性能等是否有坑。这里只介绍简单的Jboss下,mysql+hibernate+jta的简单实现。网上还有许多其他方式实现,如JTOM, atomikos方式实现的,各种方法没有做过比较及充分测试。自己学习过程的整理,如果有不对之处,请大牛指点。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值