Spring3.0已经不再支持jtom了,不过我们可以用第三方开源软件atomikos(http://www.atomikos.com/)来实现。Atomikos是目前在分布式事务管理中做得相当不错的开源软件。有10年以上的经验,Atomikos保障您的关键事务和 防止昂贵的数据丢失在发生系统故障或事故中。Atomikos支持XA(全局事务)和NON-XA(非全局事务),NON-XA效率高于XA.本文主要是讲XA事件,因为要在不同的数据库中操作多张表。
接下来说一下怎么和spring3.0结合使用。
第一步:配置ApplicationContext.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-lazy-init="true"> <!-- spring atomikos 配置 开始--> <!-- mysql数据源 --> <bean id="mysqlDS" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <description>mysql xa datasource</description> <property name="uniqueResourceName"> <value>mysql_ds</value> </property> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="xaProperties"> <props> <prop key="user">userName</prop> <prop key="password">password</prop> <prop key="URL">jdbc\:mysql\://127.0.0.1\:3306/dataBaseName?autoReconnect\=true</prop> </props> </property> <!-- 连接池里面连接的个数? --> <property name="poolSize" value="3"/> </bean> <!-- oracle数据源 --> <bean id="oracleDS" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <description>oracle xa datasource</description> <property name="uniqueResourceName"> <value>oracle_ds</value> </property> <property name="xaDataSourceClassName"> <value>oracle.jdbc.xa.client.OracleXADataSource</value> </property> <property name="xaProperties"> <props> <prop key="user">userName</prop> <prop key="password">password</prop> <prop key="URL">jdbc\:oracle\:thin\:@127.0.0.1\:1521\:dataBaseName</prop> </props> </property> <!-- 连接池里面连接的个数? --> <property name="poolSize" value="3"/> </bean> <!-- atomikos事务管理器 --> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <description>UserTransactionManager</description> <property name="forceShutdown"> <value>true</value> </property> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300" /> </bean> <!-- spring 事务管理器 --> <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <ref bean="atomikosTransactionManager" /> </property> <property name="userTransaction"> <ref bean="atomikosUserTransaction" /> </property> </bean> <!-- spring 事务模板 我在项目当中用的是编程式事务--> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager"> <ref bean="springTransactionManager" /> </property> </bean> <bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate"> <constructor-arg> <ref bean="mysqlDS" /> </constructor-arg> </bean> <bean id="simplejdbcTemplateOra" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate"> <constructor-arg> <ref bean="oracleDS" /> </constructor-arg> </bean> <!-- spring atomikos 配置 结束--> <!-- 接下来就是具体的Dao的配置 --> <bean id="oracleJtaDao" class="com.dao.TerminalOracleJtaDao"> <property name="simplejdbcTemplateOra"> <ref bean="simplejdbcTemplateOra" /> </property> <property name="transactionTemplate"> <ref bean="transactionTemplate" /> </property> </bean> <bean id="myaqlJtaDao" class="com.dao.TerminalMyaqlJtaDao"> <property name="simpleJdbcTemplate"> <ref bean="simpleJdbcTemplate" /> </property> <property name="transactionTemplate"> <ref bean="transactionTemplate" /> </property> </bean> </beans>
第二步:配置jta.properties文件,此文件是必须的。主是是设置atomikos启动的一些参数,比如日志的输出级别,日志文件的名称等
# SAMPLE PROPERTIES FILE FOR THE TRANSACTION SERVICE # THIS FILE ILLUSTRATES THE DIFFERENT SETTINGS FOR THE TRANSACTION MANAGER # UNCOMMENT THE ASSIGNMENTS TO OVERRIDE DEFAULT VALUES; # Required: factory implementation class of the transaction core. # NOTE: there is no default for this, so it MUST be specified! # com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory # Set base name of file where messages are output # (also known as the 'console file'). # com.atomikos.icatch.console_file_name = tm.out # Size limit (in bytes) for the console file; # negative means unlimited. # # com.atomikos.icatch.console_file_limit=-1 # For size-limited console files, this option # specifies a number of rotating files to # maintain. # # com.atomikos.icatch.console_file_count=1 # Set the number of log writes between checkpoints # # com.atomikos.icatch.checkpoint_interval=500 # Set output directory where console file and other files are to be put # make sure this directory exists! # # com.atomikos.icatch.output_dir = ./ # Set directory of log files; make sure this directory exists! # # com.atomikos.icatch.log_base_dir = ./ # Set base name of log file # this name will be used as the first part of # the system-generated log file name # com.atomikos.icatch.log_base_name = tmlog # Set the max number of active local transactions # or -1 for unlimited. # # com.atomikos.icatch.max_actives = 50 # Set the default timeout (in milliseconds) for local transactions # # com.atomikos.icatch.default_jta_timeout = 10000 # Set the max timeout (in milliseconds) for local transactions # # com.atomikos.icatch.max_timeout = 300000 # The globally unique name of this transaction manager process # override this value with a globally unique name # com.atomikos.icatch.tm_unique_name = tm # Do we want to use parallel subtransactions? JTA's default # is NO for J2EE compatibility # # com.atomikos.icatch.serial_jta_transactions=true # If you want to do explicit resource registration then # you need to set this value to false. # # com.atomikos.icatch.automatic_resource_registration=true # Set this to WARN, INFO or DEBUG to control the granularity # of output to the console file. # com.atomikos.icatch.console_log_level=INFO # Do you want transaction logging to be enabled or not? # If set to false, then no logging overhead will be done # at the risk of losing data after restart or crash. # # com.atomikos.icatch.enable_logging=true # Should two-phase commit be done in (multi-)threaded mode or not? # Set this to false if you want commits to be ordered according # to the order in which resources are added to the transaction. # # NOTE: threads are reused on JDK 1.5 or higher. # For JDK 1.4, thread reuse is enabled as soon as the # concurrent backport is in the classpath - see # http://mirrors.ibiblio.org/pub/mirrors/maven2/backport-util-concurrent/backport-util-concurrent/ # # com.atomikos.icatch.threaded_2pc=false # Should shutdown of the VM trigger shutdown of the transaction core too? # # com.atomikos.icatch.force_shutdown_on_vm_exit=false
第三步:需要分布事务处理的地方手动开启事务
TransactionTemplate.getTransactionTemplate().execute(new TransactionCallback(){ public Object doInTransaction(TransactionStatus status){ boolean flag = true; try { } catche (Exception e){ flag = false; } finally { if (!flag) { status.status.setRollbackOnly(); } } } })
参考:http://www.tuicool.com/articles/Qziu2i
http://www.blogjava.net/pdw2009/archive/2008/05/25/202725.html
http://www.cnblogs.com/davenkin/archive/2013/03/19/java-tranaction-8.html
关于jotm的分布式案例请参见:http://my.oschina.net/xianggao/blog/543790?fromerr=UzOHWQjT