SpringBoot 父类版本为2.1.2
org.springframework.boot spring-boot-starter-parent 2.1.2.RELEASE
org.springframework.boot
spring-boot-starter-jta-atomikos
#端口号
server:
port: 8026
# 数据库连接
# &serverTimezone=GMT%2B8 为中国东八区标准时区
spring:
datasource:
#datasource1
test01:
#jdbc-url: jdbc:mysql://127.0.0.1:3306/test01?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
url: jdbc:mysql://127.0.0.1:3306/test01?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
minPoolSize: 3
maxPoolSize: 25
maxLifetime: 20000
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
###datasource2
test02:
#jdbc-url: jdbc:mysql://127.0.0.1:3306/test02?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
url: jdbc:mysql://127.0.0.1:3306/test02?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
minPoolSize: 3
maxPoolSize: 25
maxLifetime: 20000
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
4.1 第一个实体类
package com.aop.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @Author : richard_aop.
* @Date : 2019-08-16
* @Data是集成了lombok 插件,相当于@Getter和@Setter
* 自动生成get和set方法与toString方法
*/
@Data
@ConfigurationProperties(prefix = "spring.datasource.test01")
public class DBConfig1 {
private String url;
private String username;
private String password;
private String driverClassName;
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.2 第二个实体类
@Data
@ConfigurationProperties(prefix = "spring.datasource.test02")
public class DBConfig2 {
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;
}
5.1 DataSourceConfig1
package com.aop.datasource;
import com.aop.config.DBConfig1;
import com.mysql.cj.jdbc.MysqlXADataSource;
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.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* @Author : richard_aop.
* @Date : 2019-08-16
* 读取DataSource1数据源
*/
@Configuration
// basePackages 最好分开配置 如果放在同一个文件夹可能会报错
@MapperScan(basePackages = "com.aop.test01.mapper", sqlSessionTemplateRef = "test1SqlSessionTemplate")
public class MyBatisConfig1 {
// 配置数据源
@Bean(name = "test1DataSource")
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);
// 创建 Atomikos 全局事务 相当于将本地事务注册到全局事务中
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("test1DataSource");
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 = "test1SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Bean(name = "test1SqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
5.2 DataSourceConfig2
// TODO @MapperScan(basePackages = "") 扫包范围必须制定到.mapper不然报错无效绑定声明
@Configuration
@MapperScan(basePackages = "com.aop.test02.mapper", sqlSessionTemplateRef = "test2SqlSessionTemplate")
public class MyBatisConfig2 {
// 配置数据源
@Primary
@Bean(name = "test2DataSource")
public DataSource testDataSource(DBConfig2 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("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;
}
@Primary
@Bean(name = "test2SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
}
@Primary
@Bean(name = "test2SqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
package com.aop;
import com.aop.config.DBConfig1;
import com.aop.config.DBConfig2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* @Author : richard_aop.
* @Date : 2019-08-16
*/
@SpringBootApplication
// 开启读取配置文件
@EnableConfigurationProperties(value = {DBConfig1.class, DBConfig2.class})
public class MyBatisApp {
//private static final Logger logger = LoggerFactory.getLogger(MyBatisApp.class);
public static void main(String[] args) {
SpringApplication.run(MyBatisApp.class, args);
System.out.println("SpringBoot整合多数据源!");
}
}
java.sql.SQLException: XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency
项目构建的时候的 JTA 依赖与插件都已经ok,项目还是报错。
Google和百度之后:
改正如下
当前访问mysql的账号缺少系统权限,我的是root(即admin)账户缺少 “允许执行 XA RECOVER语句”的权限:XA_RECOVER_ADMIN,以root账号访问mysql,执行“GRANT XA_RECOVER_ADMIN ON *.* TO root@'%';”语句,当然账号和IP需要根据自己的来改,此处为了节省时间直接改为*.*。
现在我的root(即admin)账户权限------>
mysql> SHOW GRANTS FOR root@'%';
+----------------------------------------------------------------+
| Grants for root@% |
+----------------------------------------------------------------+
| GRANT USAGE ON . TO root@% |
| GRANT XA_RECOVER_ADMIN ON . TO root@% |
| GRANT ALL PRIVILEGES ON snail_slow_delivery.* TO root@% |
+----------------------------------------------------------------+
以上内容如有不妥之处,请各位详细指正并留言,便于今后共同成长!