# SpringBoot多数据源配置 **Repository Path**: radish2020/springboot-dynamic-datasource ## Basic Information - **Project Name**: SpringBoot多数据源配置 - **Description**: 基于Springboot的三种多数据源配置方法 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 1 - **Created**: 2023-12-16 - **Last Updated**: 2024-03-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一、使用Spring提供的AbstractRoutingDataSource 主要代码: application.yml ``` java spring: datasource: type: com.alibaba.druid.pool.DruidDataSource radish: url: jdbc:mysql://127.0.0.1:3306/radish?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false username: root password: 123456 initial-size: 1 min-idle: 1 max-active: 20 test-on-borrow: true driver-class-name: com.mysql.cj.jdbc.Driver radish1: url: jdbc:mysql://127.0.0.1:3306/radish2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false username: root password: 123456 initial-size: 1 min-idle: 1 max-active: 20 test-on-borrow: true driver-class-name: com.mysql.cj.jdbc.Driver ``` DataSourceConfig.java ```java package com.radish.config; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; import com.radish.helper.DynamicDataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; @Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.radish") public DataSource radish() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.radish1") public DataSource radish1() { return DruidDataSourceBuilder.create().build(); } @Bean public DataSourceTransactionManager transactionManager1(DynamicDataSource radish){ DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(radish); return dataSourceTransactionManager; } @Bean public DataSourceTransactionManager transactionManager2(DynamicDataSource radish){ DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(radish); return dataSourceTransactionManager; } } ``` DynamicDataSource.java ```java package com.radish.helper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; @Component @Primary public class DynamicDataSource extends AbstractRoutingDataSource { // 当前使用的数据源标识 public static ThreadLocal name = new ThreadLocal<>(); // 写 @Autowired DataSource radish; // 读 @Autowired DataSource radish1; @Override protected Object determineCurrentLookupKey() { return name.get(); } @Override public void afterPropertiesSet() { // 为targetDataSources初始化所有数据源 Map targetDataSources=new HashMap<>(); targetDataSources.put("W",radish); targetDataSources.put("R",radish1); super.setTargetDataSources(targetDataSources); // 为defaultTargetDataSource 设置默认的数据源 super.setDefaultTargetDataSource(radish); super.afterPropertiesSet(); } } ``` # 二、使用MyBatis注册多个SqlSessionFactory 使用MyBatis多数据源,需要将MyBatis底层的DataSource、SqlSessionFactory、DataSourceTransactionManager这些核心对象一并进行手动注册。 核心代码: 读库注册 ```java @Configuration // 继承mybatis: // 1. 指定扫描的mapper接口包(主库) // 2. 指定使用sqlSessionFactory是哪个(主库) @MapperScan(basePackages = "com.radish.dao.r") public class RMybatisConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.radish") public DataSource radish() { return DruidDataSourceBuilder.create().build(); } @Bean @Primary public SqlSessionFactory rSqlSessionFactory() throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); // 指定主库 sessionFactory.setDataSource(radish()); // 指定主库对应的mapper.xml文件 /*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/r/*.xml"));*/ return sessionFactory.getObject(); } @Bean public DataSourceTransactionManager rTransactionManager() { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(radish()); return dataSourceTransactionManager; } @Bean public TransactionTemplate rTransactionTemplate(){ return new TransactionTemplate(rTransactionManager()); } } ``` 写库注册 ```java @Configuration // 继承mybatis: // 1. 指定扫描的mapper接口包(主库) // 2. 指定使用sqlSessionFactory是哪个(主库) @MapperScan(basePackages = "com.radish.dao.w", sqlSessionFactoryRef="wSqlSessionFactory") public class WMyBatisConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.radish2") public DataSource radish2() { // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource return DruidDataSourceBuilder.create().build(); } @Bean @Primary public SqlSessionFactory wSqlSessionFactory() throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); // 指定主库 sessionFactory.setDataSource(radish2()); // 指定主库对应的mapper.xml文件 /*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/order/*.xml"));*/ return sessionFactory.getObject(); } @Bean @Primary public DataSourceTransactionManager wTransactionManager(){ DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(radish2()); return dataSourceTransactionManager; } @Bean public TransactionTemplate wTransactionTemplate(){ return new TransactionTemplate(wTransactionManager()); } } ``` # 三、使用dynamic-datasource框架 dynamic-datasource是MyBaits-plus作者设计的一个多数据源开源方案。使用这个框架需要引入对应的pom依赖 ```xml com.baomidou dynamic-datasource-spring-boot-starter 3.5.0 ``` 这样就可以在SpringBoot的配置文件中直接配置多个数据源 ```yml spring: datasource: dynamic: #设置默认的数据源或者数据源组,默认值即为master primary: master #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 strict: false datasource: master: url: jdbc:mysql://127.0.0.1:3306/datasource1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false username: root password: 123456 initial-size: 1 min-idle: 1 max-active: 20 test-on-borrow: true driver-class-name: com.mysql.cj.jdbc.Driver slave_1: url: jdbc:mysql://127.0.0.1:3306/datasource2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false username: root password: 123456 initial-size: 1 min-idle: 1 max-active: 20 test-on-borrow: true driver-class-name: com.mysql.cj.jdbc.Driver ``` 这样就配置完成了master和slave_1两个数据库。 接下来在使用时,只要在对应的方法或者类上添加@DS注解即可。例如 ```java @Service public class TestServiceImpl implements ITestService { @Autowired private TestMapper testMapper; @Override @DS("slave") // 从库,如果按照下划线命名方式配置多个,可以指定前缀即可(组名) public List list() { return testMapper.list(); } @Override @DS("#session.userID") @DSTransactional public void save(PersonInfo personInfo) { testMapper.save(personInfo); } } ```