使用springboot+jta+atomikos 分布式事物管理
Posted 求知若渴的蜗牛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用springboot+jta+atomikos 分布式事物管理相关的知识,希望对你有一定的参考价值。
当项目在连接多个数据库时可能会发生事务问题,即一个库的事务不可能去操作另一个数据库的事务,这时就需要使用atomikos对数据库的事务进行统一的管理
第一步添加atomikos的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
第二步配置数据源,我这里有2个数据库(ruan和youxianqi),你有多少就加多少。
spring:
datasource:
system:
jdbc-url: jdbc:oracle:thin:@localhost:1521/orcl
driver-class-name: oracle.jdbc.OracleDriver
username: yuan
password: 1234
initial-size: 5
min-idle: 5
max-active: 20
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
kllogt:
jdbc-url: jdbc:oracle:thin:@localhost:1521/orcl
driver-class-name: oracle.jdbc.OracleDriver
username: youxianqi
password: youxianqi
initial-size: 5
min-idle: 5
max-active: 20
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
logging:
level:
org.springframework.web: debug
然后创建DBConfig1和DBConfig2,这两个实体类就是存放两个数据源的数据的。
package com.cgb.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.datasource.system")
public class DBConfig1 {
private String jdbc-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;
public String getJdbc-url() {
return url;
}
public void setJdbc-url(String jdbc-url) {
this.jdbc-url= jdbc-url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getMinPoolSize() {
return minPoolSize;
}
public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getMaxLifetime() {
return maxLifetime;
}
public void setMaxLifetime(int maxLifetime) {
this.maxLifetime = maxLifetime;
}
public int getBorrowConnectionTimeout() {
return borrowConnectionTimeout;
}
public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
this.borrowConnectionTimeout = borrowConnectionTimeout;
}
public int getLoginTimeout() {
return loginTimeout;
}
public void setLoginTimeout(int loginTimeout) {
this.loginTimeout = loginTimeout;
}
public int getMaintenanceInterval() {
return maintenanceInterval;
}
public void setMaintenanceInterval(int maintenanceInterval) {
this.maintenanceInterval = maintenanceInterval;
}
public int getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
public String getTestQuery() {
return testQuery;
}
public void setTestQuery(String testQuery) {
this.testQuery = testQuery;
}
}
然后创建两个数据源RuanMyBatisConfig和YouMyBatisConfig,注意@Primary注解只能有一个。
package com.cgb.datasource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.cgb.config.DBConfig1;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
@Configuration
@MapperScan(basePackages = "com.cgb.ruan", sqlSessionTemplateRef = "testSqlSessionTemplate")
public class RuanMyBatisConfig {
// 配置数据源
@Primary
@Bean(name = "dataSource1")
public DataSource testDataSource(DBConfig1 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("dataSource1");
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("dataSource1") 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);
}
}
其实在多个数据源的时候,我们怎么去指定数据库呢?
其中一个做法是写注解,表明使用哪个数据库,但是这种是不是很麻烦。最好的做法是分包管理:
好啦,大功告成,我们来看看效果吧。
我们发现控制台打印添加学生成功,好我们看看数据库里有没有数据呢?
毫无疑问是没有的,说明事务起作用了。那我们把那行异常代码注释掉,再看看效果。成功了,去看看数据库有没有呢。
ojbk,想想同时操作多个数据库,是不是很爽啊,哈哈哈。
以上是关于使用springboot+jta+atomikos 分布式事物管理的主要内容,如果未能解决你的问题,请参考以下文章