Click here to Skip to main content
15,883,862 members

JTA transaction management in Spring

muralitau asked:

Open original thread
>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,只有这样才能支持事务。
SQL
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
<pre lang="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

<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" >

<!-- 表名:tab_b -->
XML
<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>

<!-- 更新 -->
<update id="update" parameterclass="TabB">
update tab_b set
id = #id#,
name = #name#,
address = #address#
where id = #id#

<!-- 删除 -->
<delete id="deleteById" parameterclass="long">
delete from tab_b
where id = #value#

<!-- 根据ID获取 -->
<select id="findById" parameterClass="long" resultMap="tab_b.result_base">
select *
from tab_b
where id = #value#
</select>

/**
* 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
Java
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
<?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> 

         
        <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

<!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">


sql-map-config_B.xml

XML
<!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_();
}
}
but i can't execute this project ... what can i should modified
Tags: Java

Plain Text
ASM
ASP
ASP.NET
BASIC
BAT
C#
C++
COBOL
CoffeeScript
CSS
Dart
dbase
F#
FORTRAN
HTML
Java
Javascript
Kotlin
Lua
MIDL
MSIL
ObjectiveC
Pascal
PERL
PHP
PowerShell
Python
Razor
Ruby
Scala
Shell
SLN
SQL
Swift
T4
Terminal
TypeScript
VB
VBScript
XML
YAML

Preview



When answering a question please:
  1. Read the question carefully.
  2. Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  3. If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
  4. Don't tell someone to read the manual. Chances are they have and don't get it. Provide an answer or move on to the next question.
Let's work to help developers, not make them feel stupid.
Please note that all posts will be submitted under the http://www.codeproject.com/info/cpol10.aspx.



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900