(九)SpringBoot2.0整合atomikos分布式事务管理

文章目录

  • 一. SpringBoot整合事物管理
  • 二. SpringBoot分布式事物管理
    • 1. 新增jta-atomikos依赖
    • 2. 新增配置文件信息
    • 3. 读取配置文件信息
    • 4. 创建多数据源
    • 5. 启动加载配置
  • 三. 项目演示
  • 四. 源码地址
  • 五. 遇到的问题

一. SpringBoot整合事物管理

Springboot默认集成事物,只主要在方法上加上@Transactional即可

二. SpringBoot分布式事物管理

使用springboot+jta+atomikos 分布式事物管理
Atomikos 是一个为Java平台提供增值服务的并且开源类事务管理器。

1. 新增jta-atomikos依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2. 新增配置文件信息


# Mysql 1
mysql.datasource.test1.url = jdbc:mysql://localhost:3306/test01db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
mysql.datasource.test1.username = root
mysql.datasource.test1.password = 123456
mysql.datasource.test1.driveClassName = com.mysql.cj.jdbc.Driver

mysql.datasource.test1.minPoolSize = 3
mysql.datasource.test1.maxPoolSize = 25
mysql.datasource.test1.maxLifetime = 20000
mysql.datasource.test1.borrowConnectionTimeout = 30
mysql.datasource.test1.loginTimeout = 30
mysql.datasource.test1.maintenanceInterval = 60
mysql.datasource.test1.maxIdleTime = 60



# Mysql 2
mysql.datasource.test2.url =jdbc:mysql://localhost:3306/test02db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
mysql.datasource.test2.username =root
mysql.datasource.test2.password =123456
mysql.datasource.test2.driveClassName = com.mysql.cj.jdbc.Driver

mysql.datasource.test2.minPoolSize = 3
mysql.datasource.test2.maxPoolSize = 25
mysql.datasource.test2.maxLifetime = 20000
mysql.datasource.test2.borrowConnectionTimeout = 30
mysql.datasource.test2.loginTimeout = 30
mysql.datasource.test2.maintenanceInterval = 60
mysql.datasource.test2.maxIdleTime = 60

3. 读取配置文件信息

数据源一的配置信息:

@Data
@ConfigurationProperties(prefix = "mysql.datasource.test1")
public class DBConfigOne {

	private String url;
	private String username;
	private String password;
	private int minPoolSize;
	private int maxPoolSize;
	private int maxLifetime;
	private int borrowConnectionTimeout;
	private int loginTimeout;
	private int maintenanceInterval;
	private int maxIdleTime;
	private String testQuery;
}

数据源二的配置信息:

@Data
@ConfigurationProperties(prefix = "mysql.datasource.test2")
public class DBConfigTwo {

	private String url;
	private String username;
	private String password;
	private int minPoolSize;
	private int maxPoolSize;
	private int maxLifetime;
	private int borrowConnectionTimeout;
	private int loginTimeout;
	private int maintenanceInterval;
	private int maxIdleTime;
	private String testQuery;
}

4. 创建多数据源

第一库的数据源配置:

/**
* @desc: 数据源一
* @author:hejr
* @date:2019/4/9
*/
@Configuration
@MapperScan(basePackages = "com.hejr.test01", sqlSessionTemplateRef = "testSqlSessionTemplate")
public class MyBatisConfigOne {

	@Bean(name = "testDataSource")
	@Primary
	public DataSource testDataSource(DBConfigOne testConfig) throws SQLException {
		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
		mysqlXaDataSource.setUrl(testConfig.getUrl());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
		mysqlXaDataSource.setPassword(testConfig.getPassword());
		mysqlXaDataSource.setUser(testConfig.getUsername());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
		// 将本地事务注册到创 Atomikos全局事务
		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
		xaDataSource.setXaDataSource(mysqlXaDataSource);
		xaDataSource.setUniqueResourceName("testDataSource");

		xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
		xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
		xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
		xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
		xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
		xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
		xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
		xaDataSource.setTestQuery(testConfig.getTestQuery());
		return xaDataSource;
	}

	@Bean(name = "testSqlSessionFactory")
	public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource)
			throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		return bean.getObject();
	}

	@Bean(name = "testSqlSessionTemplate")
	public SqlSessionTemplate testSqlSessionTemplate(
			@Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}

第二个数据源的配置:

@Configuration
@MapperScan(basePackages = "com.hejr.test02", sqlSessionTemplateRef = "test2SqlSessionTemplate")
public class MyBatisConfigTwo {

	@Bean(name = "test2DataSource")
	public DataSource testDataSource(DBConfigTwo testConfig) throws SQLException {
		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
		mysqlXaDataSource.setUrl(testConfig.getUrl());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
		mysqlXaDataSource.setPassword(testConfig.getPassword());
		mysqlXaDataSource.setUser(testConfig.getUsername());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
		xaDataSource.setXaDataSource(mysqlXaDataSource);
		xaDataSource.setUniqueResourceName("test2DataSource");

		xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
		xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
		xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
		xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
		xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
		xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
		xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
		xaDataSource.setTestQuery(testConfig.getTestQuery());
		return xaDataSource;
	}

	@Bean(name = "test2SqlSessionFactory")
	public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
			throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		return bean.getObject();
	}

	@Bean(name = "test2SqlSessionTemplate")
	public SqlSessionTemplate testSqlSessionTemplate(
			@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
}

5. 启动加载配置

@EnableConfigurationProperties(value = { DBConfigOne.class, DBConfigTwo.class })

三. 项目演示

http://192.168.0.248:8080/insertUserTest01AndTest02?name=黄功利&age=0
断点查看,当执行完第一个库的插入时,刷新数据库表是没有数据的,这表明这连个事务处于同一个事务中,执行到报错一行后,查看数据库,没有插入数据,这表明整合分布式事务成功。

四. 源码地址

https://gitee.com/hejr.cn.com/SpringBoot2.0_2019/tree/master/springboot2_005

五. 遇到的问题

第一个问题:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

这是由于设置了多个数据源,需要给其中一个指定主从关系,解决如下:
同时在启动类上面加上:@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
(九)SpringBoot2.0整合atomikos分布式事务管理_第1张图片
第二个问题:
由于我当时想换成Mybatis-Plus,不使用JPA,导致报了如下错误:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.hejr.test01.mapper.UserOneMapper.insert

目前还没解决,自己有时间会去研究下,有知道的朋友请指点一下,相互学习!!!

下一篇:(十)SpringBoot2.0整合log4j+lombok日志管理

你可能感兴趣的:(SpringBoot2.0,SpringBoot2.x学习)