文章目录
  1. 1. springboot无配置多数据源分布式数据事务管理
    1. 1.1. 使用atomikos解决多数据源分布式事务问题
    2. 1.2. 主数据源配置
    3. 1.3. 副数据源配置
    4. 1.4. atomikos分布式事务配置

springboot无配置多数据源分布式数据事务管理

使用atomikos解决多数据源分布式事务问题

atomikos官网是这样描述atomikos的使用的:

It is easy to setup by using its setter methods but can also be easily built from a Spring BeanFactory. Here is an example of code that creates an AtomikosDataSourceBean with 5 connections in pool on an Oracle database:

AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
ds.setUniqueResourceName(“oracle”);
ds.setXaDataSourceClassName(“oracle.jdbc.xa.client.OracleXADataSource”);
Properties p = new Properties();
p.setProperty ( “user” , “java” );
p.setProperty ( “password” , “java” );
p.setProperty ( “URL” , “jdbc:oracle:thin:@localhost-xe:1521:XE” );
ds.setXaDataSourceProperties ( p );
ds.setPoolSize ( 5 );

可以这样设置生成database,并初始化sql:

1
2
3
4
5
6
`EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder
.setType(EmbeddedDatabaseType.H2) //等价于设置url=jdbc:h2:mem:testdb
.addScript("primarySchema.sql")
.build();
return db;

`

项目pom.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
`\<?xml version="1.0" encoding="UTF-8"?\>
\<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"\>
\<modelVersion\>4.0.0\</modelVersion\>

\<groupId\>com.example\</groupId\>
\<artifactId\>demo1\</artifactId\>
\<version\>0.0.1-SNAPSHOT\</version\>
\<packaging\>jar\</packaging\>

\<name\>demo1\</name\>
\<description\>Demo project for Spring Boot\</description\>

\<parent\>
\<groupId\>org.springframework.boot\</groupId\>
\<artifactId\>spring-boot-starter-parent\</artifactId\>
\<version\>1.5.6.RELEASE\</version\>
\<relativePath/\> \<!-- lookup parent from repository --\>
\</parent\>

\<properties\>
\<project.build.sourceEncoding\>UTF-8\</project.build.sourceEncoding\>
\<project.reporting.outputEncoding\>UTF-8\</project.reporting.outputEncoding\>
\<java.version\>1.8\</java.version\>
\</properties\>

\<dependencies\>
\<dependency\>
\<groupId\>org.springframework.boot\</groupId\>
\<artifactId\>spring-boot-starter-aop\</artifactId\>
\</dependency\>
\<dependency\>
\<groupId\>org.springframework.boot\</groupId\>
\<artifactId\>spring-boot-starter-web\</artifactId\>
\</dependency\>

\<dependency\>
\<groupId\>org.mybatis.spring.boot\</groupId\>
\<artifactId\>mybatis-spring-boot-starter\</artifactId\>
\<version\>1.3.0\</version\>
\</dependency\>
\<dependency\>
\<groupId\>org.springframework.boot\</groupId\>
\<artifactId\>spring-boot-starter-jta-atomikos\</artifactId\>
\</dependency\>

\<dependency\>
\<groupId\>com.h2database\</groupId\>
\<artifactId\>h2\</artifactId\>
\<scope\>runtime\</scope\>
\</dependency\>



\<dependency\>
\<groupId\>org.projectlombok\</groupId\>
\<artifactId\>lombok\</artifactId\>
\<optional\>true\</optional\>
\</dependency\>

\<dependency\>
\<groupId\>org.springframework.boot\</groupId\>
\<artifactId\>spring-boot-starter-test\</artifactId\>
\<scope\>test\</scope\>
\</dependency\>



\</dependencies\>

\<build\>
\<plugins\>
\<plugin\>
\<groupId\>org.springframework.boot\</groupId\>
\<artifactId\>spring-boot-maven-plugin\</artifactId\>
\</plugin\>
\</plugins\>
\</build\>

\<repositories\>
\<repository\>
\<id\>alimaven\</id\>
\<url\>http://maven.aliyun.com/nexus/content/groups/public/\</url\>
\</repository\>
\<repository\>
\<id\>spring-snapshots\</id\>
\<url\>http://repo.spring.io/snapshot\</url\>
\<snapshots\>\<enabled\>true\</enabled\>\</snapshots\>
\</repository\>
\<repository\>
\<id\>spring-milestones\</id\>
\<url\>http://repo.spring.io/milestone\</url\>
\</repository\>
\</repositories\>

\</project\>

`

主数据源配置

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
`package com.example.demo;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;

import javax.sql.DataSource;
import java.util.Properties;

/**  * Created by sam on 2017/7/30.
*/

@Configuration
@MapperScan(value = "com.example.demo.mapper.primary",sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {

@Bean(name = "primaryDataSource")
@Primary
public DataSource primaryDataSource(){
System.out.println("-------primary dataSource-------init");
AtomikosDataSourceBean dataSourceBean = new AtomikosDataSourceBean();
dataSourceBean.setXaDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
Properties pts = new Properties();
pts.setProperty("url","jdbc:h2:mem:PMDB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
pts.setProperty("user","sa");
pts.setProperty("password","");
dataSourceBean.setXaProperties(pts);
dataSourceBean.setPoolSize(1);
dataSourceBean.setMaxPoolSize(3);
return dataSourceBean;
}


//第一种方式
// @Bean(name = "primaryDataSource")
// @Primary
// @ConfigurationProperties(prefix = "primary.datasource")
// public DataSource primaryDataSource(){
// System.out.println("-------primary dataSource-------init");
// return DataSourceBuilder.create().build();
// }

//第二种方式
// @Bean(name = "primaryDataSource")
// @Primary
// public DataSource primaryDataSource(){
// System.out.println("-------primary dataSource-------init");
// EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
// EmbeddedDatabase db = builder
// .setType(EmbeddedDatabaseType.H2) //等价于设置url=jdbc:h2:mem:testdb
// .addScript("primarySchema.sql")
// .build();
// return db;
// }





@Bean
public DataSourceInitializer primaryInitSql(@Qualifier("primaryDataSource") DataSource dataSource){

return init(dataSource,"primarySchema");
}



private DataSourceInitializer init(DataSource dataSource,String schameName){
DataSourceInitializer dsi = new DataSourceInitializer();
dsi.setDataSource(dataSource);
dsi.setDatabasePopulator(new ResourceDatabasePopulator(new ClassPathResource(schameName+".sql")));
return dsi;
}



@Bean(name = "primarySqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
return sessionFactory.getObject();
}


}

`

副数据源配置

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
`package com.example.demo;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;

import javax.sql.DataSource;
import java.util.Properties;

/**  * Created by sam on 2017/7/30.
*/

@Configuration
@MapperScan(value = "com.example.demo.mapper.second",sqlSessionFactoryRef = "secondSqlSessionFactory")
public class SecondDataSourceConfig {


@Bean(name = "secondDataSource")
public DataSource secondDataSource(){
System.out.println("-------second dataSource-------init");
AtomikosDataSourceBean dataSourceBean = new AtomikosDataSourceBean();
dataSourceBean.setXaDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
Properties pts = new Properties();
pts.setProperty("url","jdbc:h2:mem:SCDB;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
pts.setProperty("user","sa");
pts.setProperty("password","");
dataSourceBean.setXaProperties(pts);
dataSourceBean.setPoolSize(1);
dataSourceBean.setMaxPoolSize(3);
return dataSourceBean;

}


@Bean
public DataSourceInitializer secondInitSql(@Qualifier("secondDataSource") DataSource dataSource){

return init(dataSource,"secondSchema");
}

private DataSourceInitializer init(DataSource dataSource,String schameName){
DataSourceInitializer dsi = new DataSourceInitializer();
dsi.setDataSource(dataSource);
dsi.setDatabasePopulator(new ResourceDatabasePopulator(new ClassPathResource(schameName+".sql")));
return dsi;
}

@Bean(name = "secondSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("secondDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
return sessionFactory.getObject();
}
}

`

atomikos分布式事务配置

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
`package com.example.demo;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.transaction.SystemException;

/**  * Created by sam on 2017/8/2.
*/
@Configuration
public class AtomikosTXAConfig implements TransactionManagementConfigurer {

@Bean(name = "atomikosTransactionManager")
public UserTransactionManager atomikosTransactionManager(){
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(true);
return userTransactionManager;
}

@Bean(name = "atomikosUserTransaction")
public UserTransactionImp atomikosUserTransaction(){
UserTransactionImp atomikosUserTransation =new UserTransactionImp();
try {
atomikosUserTransation.setTransactionTimeout(100);
} catch (SystemException e) {
e.printStackTrace();
}
return atomikosUserTransation;
}

@Bean
public JtaTransactionManager txManager() {
return new JtaTransactionManager(atomikosUserTransaction(),atomikosTransactionManager());
}


@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return txManager();
}
}

`

文章目录
  1. 1. springboot无配置多数据源分布式数据事务管理
    1. 1.1. 使用atomikos解决多数据源分布式事务问题
    2. 1.2. 主数据源配置
    3. 1.3. 副数据源配置
    4. 1.4. atomikos分布式事务配置