业务背景:
6、测试类:
假定我们有这样一个需求:当我们新建一个用户的时候需要往一个DB中插入一条用户记录,还需要往另一个DB中记录日志。因为是不同的DB操作,所以这里就涉及到分布式事务的处理。
1、代码结构:
2、建表语句:
create database log;
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` varchar(20) NOT NULL,
`content` varchar(100) default NULL,
PRIMARY KEY (`id`)
);
create database user;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` varchar(20) NOT NULL,
`name` varchar(40) default NULL,
PRIMARY KEY (`id`)
);
3、配置文件application.xml
<!--?xml version=1.0 encoding=UTF-8?-->
<beans aop="" beans="" http:="" schema="" spring-aop.xsd="" spring-beans.xsd="" spring-tx.xsd="" tx="" www.springframework.org="" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans">
<!-- 引用Spring内部所提供的对JOTM支持的工厂类 -->
<bean class="org.springframework.transaction.jta.JotmFactoryBean" id="jotm">
<!-- 配置JTA事务管理器, 并在管理器中使用上面所配置的JOTM -->
<bean class="org.springframework.transaction.jta.JtaTransactionManager" id="txManager">
<property name="userTransaction" ref="jotm">
</property></bean>
<!-- 配置多个数据源 -->
<bean class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown" id="db1">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager" ref="jotm">
<property name="driverName" value="com.mysql.jdbc.Driver">
<property name="url" value="jdbc:MySQL://localhost:3306/user">
</property></property></property></bean>
</property>
<property name="user" value="root">
<property name="password" value="root">
</property></property></bean>
<bean class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown" id="db2">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager" ref="jotm">
<property name="driverName" value="com.mysql.jdbc.Driver">
<property name="url" value="jdbc:MySQL://localhost:3306/log">
</property></property></property></bean>
</property>
<property name="user" value="root">
<property name="password" value="root">
</property></property></bean>
<!-- 根据不同的数据源配置两个jdbcTemplate -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate1">
<property name="dataSource" ref="db1">
</property></bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate2">
<property name="dataSource" ref="db2">
</property></bean>
<bean class="com.zdp.dao.UserDao" id="userDao">
<property name="jdbcTemplate" ref="jdbcTemplate1">
</property></bean>
<bean class="com.zdp.dao.LogDao" id="logDao">
<property name="jdbcTemplate" ref="jdbcTemplate2">
</property></bean>
<bean class="com.zdp.service.UserService" id="userService">
<property name="userDao" ref="userDao">
<property name="logDao" ref="logDao">
</property></property></bean>
<!-- JTA事务传播特性 -->
<tx:advice id="txAdviceJTA" transaction-manager="txManager">
<tx:attributes>
<tx:method isolation="DEFAULT" name="save*" propagation="REQUIRED" rollback-for="Exception/">
<tx:method isolation="DEFAULT" name="add*" propagation="REQUIRED" rollback-for="Exception/">
<tx:method isolation="DEFAULT" name="create*" propagation="REQUIRED" rollback-for="Exception/">
<tx:method isolation="DEFAULT" name="insert*" propagation="REQUIRED" rollback-for="Exception/">
<tx:method isolation="DEFAULT" name="del*" propagation="REQUIRED" rollback-for="Exception/">
<tx:method isolation="DEFAULT" name="update*" propagation="REQUIRED" rollback-for="Exception/">
<tx:method name="*" read-only="true/">
</tx:method></tx:method></tx:method></tx:method></tx:method></tx:method></tx:method></tx:attributes>
</tx:advice>
</aop:advisor></aop:config>
</bean></beans>
4、service业务类:
public class UserService {
private UserDao userDao;
private LogDao logDao;
public void saveUser(String id, String name) {
userDao.insertUser(id, name);
// int i = 1 / 0; // 制造异常
logDao.insertLog(id, id + _ + name);
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public LogDao getLogDao() {
return logDao;
}
public void setLogDao(LogDao logDao) {
this.logDao = logDao;
}
}
5、dao类:
public class UserDao extends JdbcDaoSupport {
public void insertUser(String id, String name) {
JdbcTemplate template = getJdbcTemplate();
template.execute(insert into user values(' + id + ',' + name + '));
}
}
public class LogDao extends JdbcDaoSupport {
public void insertLog(String id, String content) {
JdbcTemplate template = getJdbcTemplate();
template.execute(insert into log values(' + id + ',' + content + '));
}
}
6、测试类:
public class UserTest {
@Test
public void testSave() {
ApplicationContext cxt = new ClassPathXmlApplicationContext(ApplicationContext.xml);
UserService us = (UserService) cxt.getBean(userService);
us.saveUser(1, zhangsan);
}
}