Springboot + Atomikos + Druid + Mysql 实现JTA分布式事务

DataSource 配置
 1 package com.cheng.dynamic.config;
 2 
 3 import java.util.Properties;
 4 
 5 import javax.sql.DataSource;
 6 
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
 9 import org.springframework.context.annotation.Bean;
10 import org.springframework.context.annotation.Configuration;
11 import org.springframework.context.annotation.Primary;
12 import org.springframework.core.env.Environment;
13 
14 @Configuration
15 public class DataSourceConfig {
16     @Autowired
17     private Environment env;
18     
19     @Bean(name = "primaryDS")
20     @Primary
21     public DataSource primaryDataSource() throws Exception{
22         AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
23         ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
24         ds.setUniqueResourceName("primaryRN");
25         ds.setPoolSize(5);
26         ds.setXaProperties(build("cheng.primary.datasource."));
27         return ds;
28     }
29     
30     @Bean(name = "secondaryDS")
31     public DataSource dataSource() throws Exception{
32         AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
33         ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
34         ds.setUniqueResourceName("secondaryRN");
35         ds.setPoolSize(5);
36         ds.setXaProperties(build("cheng.secondary.datasource."));
37         return ds;
38     }
39     
40     private Properties build(String prefix) {
41         Properties prop = new Properties();
42         prop.put("url", env.getProperty(prefix + "url"));
43         prop.put("username", env.getProperty(prefix + "username"));
44         prop.put("password", env.getProperty(prefix + "password"));
45         prop.put("driverClassName", env.getProperty(prefix + "driverClassName"));
46 
47         return prop;
48     }
49 }

JtaTransactionManagerConfig

 1 package com.cheng.dynamic.config;
 2 
 3 import javax.transaction.UserTransaction;
 4 
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.transaction.jta.JtaTransactionManager;
 8 
 9 import com.atomikos.icatch.jta.UserTransactionImp;
10 import com.atomikos.icatch.jta.UserTransactionManager;
11 
12 @Configuration
13 public class JtaTransactionManagerConfig {
14     @Bean(name = "xatx")
15     public JtaTransactionManager regTransactionManager () {
16         UserTransactionManager userTransactionManager = new UserTransactionManager();
17         UserTransaction userTransaction = new UserTransactionImp();
18         return new JtaTransactionManager(userTransaction, userTransactionManager);
19     }
20 }

RepositoryPrimaryConfig

 1 package com.cheng.dynamic.config;
 2 
 3 import javax.sql.DataSource;
 4 
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.mybatis.spring.SqlSessionFactoryBean;
 7 import org.mybatis.spring.SqlSessionTemplate;
 8 import org.mybatis.spring.annotation.MapperScan;
 9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.beans.factory.annotation.Qualifier;
11 import org.springframework.context.annotation.Bean;
12 import org.springframework.context.annotation.Configuration;
13 import org.springframework.context.annotation.Primary;
14 import org.springframework.core.env.Environment;
15 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
16 
17 @Configuration
18 @MapperScan(basePackages = "com.cheng.dynamic.repository.primary", sqlSessionTemplateRef  = "sqlSessionTemplatePrimary")
19 public class RepositoryPrimaryConfig {
20     @Autowired
21     private Environment env;
22     @Autowired 
23     @Qualifier("primaryDS")
24     private DataSource primaryDS;
25     
26     @Bean(name="sqlSessionFactoryPrimary")
27     @Primary
28     public SqlSessionFactory sqlSessionFactoryPrimary() throws Exception{
29         SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
30         fb.setDataSource(primaryDS);
31         fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));//指定基包
32         fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapperLocations")));//指定xml文件位置
33         return fb.getObject();
34     }
35     
36     @Bean(name = "sqlSessionTemplatePrimary")
37     @Primary
38     public SqlSessionTemplate sqlSessionTemplatePrimary(@Qualifier("sqlSessionFactoryPrimary") SqlSessionFactory sqlSessionFactory) throws Exception {
39         SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
40         return sqlSessionTemplate;
41     }
42 }

RepositorySecondaryConfig

 1 package com.cheng.dynamic.config;
 2 
 3 import javax.sql.DataSource;
 4 
 5 import org.apache.ibatis.session.SqlSessionFactory;
 6 import org.mybatis.spring.SqlSessionFactoryBean;
 7 import org.mybatis.spring.SqlSessionTemplate;
 8 import org.mybatis.spring.annotation.MapperScan;
 9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.beans.factory.annotation.Qualifier;
11 import org.springframework.context.annotation.Bean;
12 import org.springframework.context.annotation.Configuration;
13 import org.springframework.core.env.Environment;
14 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
15 
16 @Configuration
17 @MapperScan(basePackages = "com.cheng.dynamic.repository.secondary", sqlSessionTemplateRef  = "sqlSessionTemplateSecondary")
18 public class RepositorySecondaryConfig {
19     @Autowired
20     private Environment env;
21     @Autowired 
22     @Qualifier("secondaryDS")
23     private DataSource secondaryDS;
24 
25     @Bean(name="sqlSessionFactorySecondary")
26     public SqlSessionFactory sqlSessionFactorySecondary() throws Exception{
27         SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
28         fb.setDataSource(secondaryDS);
29         fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage2"));//指定基包
30         fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapperLocations2")));//指定xml文件位置
31         return fb.getObject();
32     }
33     
34     @Bean(name = "sqlSessionTemplateSecondary")
35     public SqlSessionTemplate sqlSessionTemplateSecondary(@Qualifier("sqlSessionFactorySecondary") SqlSessionFactory sqlSessionFactory) throws Exception {
36         return new SqlSessionTemplate(sqlSessionFactory);
37     }
38 }

Test1Service

 1 package com.cheng.dynamic.service;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Service;
 5 import org.springframework.transaction.annotation.Transactional;
 6 
 7 import com.cheng.dynamic.entity.Test1;
 8 import com.cheng.dynamic.entity.Test2;
 9 import com.cheng.dynamic.repository.primary.Test1Dao;
10 
11 @Service
12 @Transactional
13 public class Test1Service {
14     @Autowired
15     private Test1Dao test1Dao;
16     @Autowired
17     private Test2Service test2Service;
18     
19     public void test(){
20         System.out.println(test1Dao);
21     }
22     
23     public void add(Test1 t){
24         System.out.println(test1Dao.add(t));
25         System.out.println(t.getId());
26     }
27     
28     public void save(){
29         Test1 t1 = new Test1();
30         t1.setName("t1");
31         add(t1);
32 //        System.out.println(1/0);
33         Test2 t2 = new Test2();
34         t2.setName("t2");
35         test2Service.add(t2);
36     }
37 }

测试类

 1 package com.cheng.dynamic.service;
 2 
 3 import org.junit.Test;
 4 import org.junit.runner.RunWith;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.boot.test.context.SpringBootTest;
 7 import org.springframework.test.annotation.Rollback;
 8 import org.springframework.test.context.junit4.SpringRunner;
 9 import org.springframework.transaction.annotation.Transactional;
10 
11 @RunWith(SpringRunner.class)
12 @SpringBootTest()
13 @Transactional(transactionManager = "xatx")
14 @Rollback(false)
15 public class Test1ServiceTest {
16     @Autowired
17     private Test1Service test1Service;
18     @Test
19     public void testTest() throws Exception {
20         test1Service.save();
21     }
22 
23 }

druid监控配置

 1 package com.cheng.dynamic.config;
 2 
 3 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 4 import org.springframework.boot.web.servlet.ServletRegistrationBean;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 
 8 import com.alibaba.druid.filter.stat.StatFilter;
 9 import com.alibaba.druid.support.http.StatViewServlet;
10 import com.alibaba.druid.support.http.WebStatFilter;
11 import com.alibaba.druid.wall.WallConfig;
12 import com.alibaba.druid.wall.WallFilter;
13 
14 @Configuration
15 public class DruidConfig {
16      @Bean
17         public ServletRegistrationBean<StatViewServlet> druidServlet() {
18             ServletRegistrationBean<StatViewServlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
19 
20             //控制台管理用户,加入下面2行 进入druid后台就需要登录
21             //servletRegistrationBean.addInitParameter("loginUsername", "admin");
22             //servletRegistrationBean.addInitParameter("loginPassword", "admin");
23             return servletRegistrationBean;
24         }
25 
26         @Bean
27         public FilterRegistrationBean<WebStatFilter> filterRegistrationBean() {
28             FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>();
29             filterRegistrationBean.setFilter(new WebStatFilter());
30             filterRegistrationBean.addUrlPatterns("/*");
31             filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
32             filterRegistrationBean.addInitParameter("profileEnable", "true");
33             return filterRegistrationBean;
34         }
35 
36         @Bean
37         public StatFilter statFilter(){
38             StatFilter statFilter = new StatFilter();
39             statFilter.setLogSlowSql(true); //slowSqlMillis用来配置SQL慢的标准,执行时间超过slowSqlMillis的就是慢。
40             statFilter.setMergeSql(true); //SQL合并配置
41             statFilter.setSlowSqlMillis(1000);//slowSqlMillis的缺省值为3000,也就是3秒。
42             return statFilter;
43         }
44 
45         @Bean
46         public WallFilter wallFilter(){
47             WallFilter wallFilter = new WallFilter();
48             //允许执行多条SQL
49             WallConfig config = new WallConfig();
50             config.setMultiStatementAllow(true);
51             wallFilter.setConfig(config);
52             return wallFilter;
53         }
54 }

完整代码:https://github.com/lucheng/jta.git

其它:

SpringBoot 多数据源配置 https://github.com/lucheng/dynamic.git

SpringBoot 多数据源 + 动态数据源配置:https://github.com/lucheng/dynamicDatasource.git

原文地址:https://www.cnblogs.com/tusheng/p/9077309.html