java分布式事务:spring+JTA+jotm

中国人最喜欢访问的网站
只要注册ofo就送你10块钱,还等什么,快来注册吧

业务背景

当新建用户时需插入一条用户记录,同时还需在另一个DB中记录日志。因为是不同的DB操作,所以及到分布式事务的处理。

1、代码结构:

项目在eclipse中

2、建表语句:

1
2
3
4
5
6
7
create database log;
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` varchar(20) NOT NULL,
`content` varchar(100) default NULL,
PRIMARY KEY (`id`)
);
1
2
3
4
5
6
7
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!--?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"/>
</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"/>
</bean>
</property>
<property name="user" value="root"/>
<property name="password" value="root"/>
</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"/>
</bean>
</property>
<property name="user" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- 根据不同的数据源配置两个jdbcTemplate -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate1">
<property name="dataSource" ref="db1"/>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate2">
<property name="dataSource" ref="db2"/>
</bean>
<bean class="com.zdp.dao.UserDao" id="userDao">
<property name="jdbcTemplate" ref="jdbcTemplate1"/>
</bean>
<bean class="com.zdp.dao.LogDao" id="logDao">
<property name="jdbcTemplate" ref="jdbcTemplate2"/>
</bean>
<bean class="com.zdp.service.UserService" id="userService"/>
<property name="userDao" ref="userDao"/>
<property name="logDao" ref="logDao"/>
</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:attributes>
</tx:advice>
</beans>

4、service业务类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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类:

1
2
3
4
5
6
public class UserDao extends JdbcDaoSupport {
public void insertUser(String id, String name) {
JdbcTemplate template = getJdbcTemplate();
template.execute(insert into user values(' + id + ',' + name + '));
}
}
1
2
3
4
5
6
public class LogDao extends JdbcDaoSupport {
public void insertLog(String id, String content) {
JdbcTemplate template = getJdbcTemplate();
template.execute(insert into log values(' + id + ',' + content + '));
}
}

6、测试类:

1
2
3
4
5
6
7
8
public class UserTest {
@Test
public void testSave() {
ApplicationContext cxt = new ClassPathXmlApplicationContext(ApplicationContext.xml);
UserService us = (UserService) cxt.getBean(userService);
us.saveUser(1, zhangsan);
}
}
快下载安装吧,今天头条送你钱啦!!!!
中国人都在使用的地球上最好玩的游戏
中国人都在使用的地球上最好玩的游戏
中国人都在使用的地球上最快的浏览器
中国人都在使用的地球上最厉害的安全软件
中国人都在使用的地球上最好的看图王
中国人都在使用的地球上最快速的视频软件
中国人都在使用的地球上最全的视频软件
中国人都在使用的地球上最好最全的压缩软件
中国人都在使用的地球上最好的音乐播放器
中国人都在使用的地球上最安全的杀毒软件
中国人都在使用的地球上最全的影视大全