- Spring+iBatis+JOTM实现JTA事务
- JOTM是个开源的JTA事务管理组件,可以让程序脱离J2EE容器而获得分布式事务管理的能力。
- 测试过程如下:
- 一、环境
- 1、准备软件环境
- spring-framework-2.5.6.SEC01-with-dependencies.zip
- ibatis-2.3.4
- ow2-jotm-dist-2.1.4-bin.tar.gz
- MySQL-5.1
- JDK1.5
- 2、创建数据库环境,注意数据库引擎为InnoDB,只有这样才能支持事务。
- CREATE DATABASE IF NOT EXISTS testdb_a DEFAULT CHARACTER SET utf8;
- USE testdb_a;
- DROP TABLE IF EXISTS tab_a;
- CREATE TABLE tab_a (
- id bigint(20) NOT NULL,
- name varchar(60) DEFAULT NULL,
- address varchar(120) DEFAULT NULL,
- PRIMARY KEY (id)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- CREATE DATABASE IF NOT EXISTS testdb_b DEFAULT CHARACTER SET utf8;
- USE testdb_b;
- DROP TABLE IF EXISTS tab_b;
- CREATE TABLE tab_b (
- id bigint(20) NOT NULL,
- name varchar(60) DEFAULT NULL,
- address varchar(120) DEFAULT NULL,
- PRIMARY KEY (id)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 二、建立项目testJOTM
- 1、建立项目后,准备依赖的类库,结构如下:
- │ spring-aop.jar
- │ spring-beans.jar
- │ spring-context-support.jar
- │ spring-context.jar
- │ spring-core.jar
- │ spring-jdbc.jar
- │ spring-jms.jar
- │ spring-orm.jar
- │ spring-test.jar
- │ spring-tx.jar
- │ spring-web.jar
- │ spring-webmvc-portlet.jar
- │ spring-webmvc-struts.jar
- │ spring-webmvc.jar
- │ aspectjrt.jar
- │ aspectjweaver.jar
- │ cglib-nodep-2.1_3.jar
- │ asm-2.2.3.jar
- │ log4j-1.2.15.jar
- │ asm-commons-2.2.3.jar
- │ asm-util-2.2.3.jar
- │ aopalliance.jar
- │ mysql-connector-java-5.1.6-bin.jar
- │
- ├─ibatis
- │ ibatis-2.3.4.726.jar
- │ sql-map-2.dtd
- │ sql-map-config-2.dtd
- │
- ├─jotm
- │ license.txt
- │ xapool.jar
- │ jotm-core.jar
- │ jotm-standalone.jar
- │ jotm-jms.jar
- │ jotm-datasource.jar
- │ ow2-jta-1.1-spec.jar
- │ jotm-client.jar
- │
- ├─jakarta-commons
- │ commons-attributes-api.jar
- │ commons-attributes-compiler.jar
- │ commons-beanutils.jar
- │ commons-codec.jar
- │ commons-collections.jar
- │ commons-dbcp.jar
- │ commons-digester.jar
- │ commons-discovery.jar
- │ commons-fileupload.jar
- │ commons-httpclient.jar
- │ commons-io.jar
- │ commons-lang.jar
- │ commons-logging.jar
- │ commons-pool.jar
- │ commons-validator.jar
- │
- ├─junit
- │ junit-3.8.2.jar
- │ junit-4.4.jar
- │ license.txt
- │
- └─log4j
- log4j-1.2.15.jar
- 2、根据表建立entity和SQLMap
- public class TabA implements Serializable {
- private Long id;
- private String name;
- private String address;
- //省略getter/setter
- public class TabB implements Serializable {
- private Long id;
- private String name;
- private String address;
- //省略getter/setter
- TabA.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" >
- <!-- 表名:tab_a -->
- <sqlMap namespace="tab_a">
- <typeAlias alias="TabA" type="com.lavasoft.stu.jtom.entity.TabA"/>
- <resultMap id="result_base" class="TabA">
- <result property="id" column="id"/>
- <result property="name" column="name"/>
- <result property="address" column="address"/>
- </resultMap>
- <!-- 添加 -->
- <insert id="insert" parameterClass="TabA">
- insert into tab_a(
- id,
- name,
- address
- ) values (
- #id#,
- #name#,
- #address#
- )
- <selectKey keyProperty="id" resultClass="long">
- select LAST_INSERT_ID()
- </selectKey>
- </insert>
- <!-- 更新 -->
- <update id="update" parameterClass="TabA">
- update tab_a set
- id = #id#,
- name = #name#,
- address = #address#
- where id = #id#
- </update>
- <!-- 删除 -->
- <delete id="deleteById" parameterClass="long">
- delete from tab_a
- where id = #value#
- </delete>
- <!-- 根据ID获取 -->
- <select id="findById" parameterClass="long" resultMap="tab_a.result_base">
- select *
- from tab_a
- where id = #value#
- </select>
- </sqlMap>
- TabB.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" >
- <!-- 表名:tab_b -->
- <sqlMap namespace="tab_b">
- <typeAlias alias="TabB" type="com.lavasoft.stu.jtom.entity.TabB"/>
- <resultMap id="result_base" class="TabB">
- <result property="id" column="id"/>
- <result property="name" column="name"/>
- <result property="address" column="address"/>
- </resultMap>
- <!-- 添加 -->
- <insert id="insert" parameterClass="TabB">
- insert into tab_b(
- id,
- name,
- address
- ) values (
- #id#,
- #name#,
- #address#
- )
- <selectKey keyProperty="id" resultClass="long">
- select LAST_INSERT_ID()
- </selectKey>
- </insert>
- <!-- 更新 -->
- <update id="update" parameterClass="TabB">
- update tab_b set
- id = #id#,
- name = #name#,
- address = #address#
- where id = #id#
- </update>
- <!-- 删除 -->
- <delete id="deleteById" parameterClass="long">
- delete from tab_b
- where id = #value#
- </delete>
- <!-- 根据ID获取 -->
- <select id="findById" parameterClass="long" resultMap="tab_b.result_base">
- select *
- from tab_b
- where id = #value#
- </select>
- </sqlMap>
- /**
- * TabADAO
- *
- * @author leizhimin 2009-6-25 12:39:19
- */
- public interface TabADAO {
- /**
- * 保存一个TabA对象
- *
- * @param tabA TabA对象
- * @return 返回保存后的对象
- */
- TabA saveTabA(TabA tabA);
- /**
- * 更新一个TabA
- *
- * @param tabA TabA对象
- * @return 返回更新后的对象
- */
- TabA updateTabA(TabA tabA);
- /**
- * 删除指定标识的一个TabA
- *
- * @param id TabA标识
- */
- void deleteTabAById(Long id);
- /**
- * 获取指定标识的TabA
- *
- * @param id TabA标识
- * @return 所查询到的TabA
- */
- TabA findTabAById(Long id);
- }
- /**
- * TabADAO
- *
- * @author leizhimin 2009-6-25 12:43:55
- */
- public class TabADAOImpl extends SqlMapClientDaoSupport implements TabADAO {
- /**
- * 保存一个TabA对象
- *
- * @param tabA TabA对象
- * @return 返回保存后的对象
- */
- public TabA saveTabA(TabA tabA) {
- Long id = (Long) getSqlMapClientTemplate().insert("tab_a.insert", tabA);
- tabA.setId(id);
- return tabA;
- }
- /**
- * 更新一个TabA
- *
- * @param tabA TabA对象
- * @return 返回更新后的对象
- */
- public TabA updateTabA(TabA tabA) {
- getSqlMapClientTemplate().update("tab_a.update", tabA);
- return tabA;
- }
- /**
- * 删除指定标识的一个TabA
- *
- * @param id TabA标识
- */
- public void deleteTabAById(Long id) {
- getSqlMapClientTemplate().delete("tab_a.deleteById",id);
- }
- /**
- * 获取指定标识的TabA
- *
- * @param id TabA标识
- * @return 所查询到的TabA
- */
- public TabA findTabAById(Long id) {
- return (TabA) getSqlMapClientTemplate().queryForObject("tab_a.findById",id);
- }
- }
- B的DAO和A类似,就不写了。
- /**
- * 测试JOTM的Service
- *
- * @author leizhimin 2009-6-25 12:53:55
- */
- public interface StuJotmService {
- /**
- * 同时保存TabA、TabB
- *
- * @param a TabA对象
- * @param b TabB对象
- */
- void saveAB(TabA a, TabB b);
- /**
- * 同时更新TabA、TabB
- *
- * @param a TabA对象
- * @param b TabB对象
- */
- void updateAB(TabA a, TabB b);
- /**
- * 删除指定id的TabA、TabB记录
- *
- * @param id 指定id
- */
- void deleteABif(Long id);
- }
- /**
- * Created by IntelliJ IDEA.
- *
- * @author leizhimin 2009-6-25 12:58:48
- */
- //@Transactional
- public class StuJotmServiceImpl implements StuJotmService {
- private TabADAO tabADAO;
- private TabBDAO tabBDAO;
- /**
- * 同时保存TabA、TabB
- *
- * @param a TabA对象
- * @param b TabB对象
- */
- // @Transactional(readOnly=false)
- public void saveAB(TabA a, TabB b) {
- tabADAO.saveTabA(a);
- tabBDAO.saveTabB(b);
- }
- /**
- * 同时更新TabA、TabB
- *
- * @param a TabA对象
- * @param b TabB对象
- */
- // @Transactional(readOnly=false)
- public void updateAB(TabA a, TabB b) {
- tabADAO.updateTabA(a);
- tabBDAO.updateTabB(b);
- }
- /**
- * 删除指定id的TabA、TabB记录
- *
- * @param id 指定id
- */
- // @Transactional(readOnly=false)
- public void deleteABif(Long id) {
- tabADAO.deleteTabAById(id);
- tabBDAO.deleteTabBById(id);
- }
- public void setTabADAO(TabADAO tabADAO) {
- this.tabADAO = tabADAO;
- }
- public void setTabBDAO(TabBDAO tabBDAO) {
- this.tabBDAO = tabBDAO;
- }
- }
- /**
- * Spring上下文工具
- *
- * @author leizhimin 2008-8-13 14:42:58
- */
- public class ApplicationContextUtil {
- private static ApplicationContext applicationContext;
- static {
- if (applicationContext == null)
- applicationContext = rebuildApplicationContext();
- }
- /**
- * 重新构建Spring应用上下文环境
- *
- * @return ApplicationContext
- */
- public static ApplicationContext rebuildApplicationContext() {
- return new ClassPathXmlApplicationContext("/ApplicationContext.xml");
- }
- /**
- * 获取Spring应用上下文环境
- *
- * @return
- */
- public static ApplicationContext getApplicationContext() {
- return applicationContext;
- }
- /**
- * 简单的上下文环境测试
- */
- public static void main(String[] args) {
- rebuildApplicationContext();
- if (applicationContext == null) {
- System.out.println("ApplicationContext is null");
- } else {
- System.out.println("ApplicationContext is not null!");
- }
- }
- }
- 三、做JTOM、Spring、iBatis、Log4j等配置
- JOTM配置:carol.properties
- #JNDI调用协议
- carol.protocols=jrmp
- #不使用CAROL JNDI封装器
- carol.start.jndi=false
- #不启动命名服务器
- carol.start.ns=false
- Spring配置: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:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
- <!--指定Spring配置中用到的属性文件-->
- <bean id="propertyConfig"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <list>
- <value>classpath:jdbc.properties</value>
- </list>
- </property>
- </bean>
- <!-- JOTM实例 -->
- <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
- <!-- JTA事务管理器 -->
- <bean id="myJtaManager"
- class="org.springframework.transaction.jta.JtaTransactionManager">
- <property name="userTransaction">
- <ref local="jotm"/>
- </property>
- </bean>
- <!-- 数据源A -->
- <bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
- <property name="dataSource">
- <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
- <property name="transactionManager" ref="jotm"/>
- <property name="driverName" value="${jdbc.driver}"/>
- <property name="url" value="${jdbc.url}"/>
- </bean>
- </property>
- <property name="user" value="${jdbc.username}"/>
- <property name="password" value="${jdbc.password}"/>
- </bean>
- <!-- 数据源B -->
- <bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
- <property name="dataSource">
- <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
- <property name="transactionManager" ref="jotm"/>
- <property name="driverName" value="${jdbc2.driver}"/>
- <property name="url" value="${jdbc2.url}"/>
- </bean>
- </property>
- <property name="user" value="${jdbc2.username}"/>
- <property name="password" value="${jdbc.password}"/>
- </bean>
- <!-- 事务切面配置 -->
- <aop:config>
- <aop:pointcut id="serviceOperation"
- expression="execution(* *..servi1ce*..*(..))"/>
- <aop:advisor pointcut-ref="serviceOperation"
- advice-ref="txAdvice"/>
- </aop:config>
- <!-- 通知配置 -->
- <tx:advice id="txAdvice" transaction-manager="myJtaManager">
- <tx:attributes>
- <tx:method name="delete*" rollback-for="Exception"/>
- <tx:method name="save*" rollback-for="Exception"/>
- <tx:method name="update*" rollback-for="Exception"/>
- <tx:method name="*" read-only="true" rollback-for="Exception"/>
- </tx:attributes>
- </tx:advice>
- <!--根据dataSourceA和sql-map-config_A.xml创建一个SqlMapClientA-->
- <bean id="sqlMapClientA"
- class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
- <property name="dataSource">
- <ref local="dataSourceA"/>
- </property>
- <property name="configLocation">
- <value>sql-map-config_A.xml</value>
- </property>
- </bean>
- <!--根据dataSourceB和sql-map-config_B.xml创建一个SqlMapClientB-->
- <bean id="sqlMapClientB"
- class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
- <property name="dataSource">
- <ref local="dataSourceB"/>
- </property>
- <property name="configLocation">
- <value>sql-map-config_B.xml</value>
- </property>
- </bean>
- <!--根据sqlMapClientA创建一个SqlMapClientTemplate的模版类实例sqlMapClientTemplateA-->
- <bean id="sqlMapClientTemplateA"
- class="org.springframework.orm.ibatis.SqlMapClientTemplate">
- <property name="sqlMapClient" ref="sqlMapClientA"/>
- </bean>
- <!--根据sqlMapClientB创建一个SqlMapClientTemplate的模版类实例sqlMapClientTemplateB-->
- <bean id="sqlMapClientTemplateB"
- class="org.springframework.orm.ibatis.SqlMapClientTemplate">
- <property name="sqlMapClient" ref="sqlMapClientB"/>
- </bean>
- <!-- 配置DAO,并注入所使用的sqlMapClientTemplate实例 -->
- <bean id="tabADAO" class="com.lavasoft.stu.jtom.dao.impl.TabADAOImpl">
- <property name="sqlMapClientTemplate" ref="sqlMapClientTemplateA"/>
- </bean>
- <bean id="tabBDAO" class="com.lavasoft.stu.jtom.dao.impl.TabBDAOImpl">
- <property name="sqlMapClientTemplate" ref="sqlMapClientTemplateB"/>
- </bean>
- <!-- Service配置,注入DAO -->
- <bean id="stuJotmService" class="com.lavasoft.stu.jtom.service.StuJotmServiceImpl">
- <property name="tabADAO" ref="tabADAO"/>
- <property name="tabBDAO" ref="tabBDAO"/>
- </bean>
- </beans>
- 数据库配置:jdbc.properties
- jdbc.database=cms_release
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://192.168.0.2:3306/testdb_a?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
- jdbc.username=root
- jdbc.password=leizhimin
- jdbc2.database=cms_release
- jdbc2.driver=com.mysql.jdbc.Driver
- jdbc2.url=jdbc:mysql://192.168.0.1:3306/testdb_b?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
- jdbc2.username=root
- jdbc2.password=leizhimin
- iBatis的SQLMap配置:
- sql-map-config_A.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE sqlMapConfig
- PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
- "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
- <sqlMapConfig>
- <settings cacheModelsEnabled="true" enhancementEnabled="true"
- lazyLoadingEnabled="true" errorTracingEnabled="true"
- useStatementNamespaces="true"/>
- <sqlMap resource="com/lavasoft/stu/jtom/entity/sqlmap/TabA.xml"/>
- </sqlMapConfig>
- sql-map-config_B.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE sqlMapConfig
- PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
- "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
- <sqlMapConfig>
- <settings cacheModelsEnabled="true" enhancementEnabled="true"
- lazyLoadingEnabled="true" errorTracingEnabled="true"
- useStatementNamespaces="true"/>
- <sqlMap resource="com/lavasoft/stu/jtom/entity/sqlmap/TabB.xml"/>
- </sqlMapConfig>
- 日志的配置:log4j.properties
- log4j.rootLogger=INFO,CONSOLE,LOGFILE
- log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
- log4j.appender.Threshold=INFO
- log4j.appender.CONSOLE.Target=System.out
- log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
- log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss } - %-5p %c %x - %m%n
- log4j.appender.LOGFILE=org.apache.log4j.RollingFileAppender
- log4j.appender.LOGFILE.File=contestlog.log
- log4j.appender.LOGFILE.MaxFileSize=500KB
- log4j.appender.LOGFILE.MaxBackupIndex=10
- log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
- log4j.appender.LOGFILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss } - %-p %c %x - %m%n
- log4j.logger.com.ibatis=INFO
- log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=INFO
- log4j.logger.com.ibatis.common.jdbc.ScriptRunner=INFO
- log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=INFO
- log4j.logger.java.sql.Connection=debug
- log4j.logger.java.sql.Statement=INFO,CONSOLE
- log4j.logger.java.sql.PreparedStatement=INFO,CONSOLE
- 四、测试
- public class Test {
- private static ApplicationContext ctx = ApplicationContextUtil.getApplicationContext();
- private static StuJotmService ser = (StuJotmService) ctx.getBean("stuJotmService");
- public static void test_() {
- TabA a = new TabA();
- a.setId(1L);
- a.setName("aaa");
- a.setAddress("address a");
- TabB b = new TabB();
- b.setId(1L);
- b.setName("bbb");
- b.setAddress("address b");
- ser.saveAB(a, b);
- }
- public static void main(String[] args) {
- test_();
- }
- }
Spring_ibatis_jta多数据源配置
最新推荐文章于 2021-04-11 17:09:11 发布