An article teaches you how to configure multiple data sources in Springboot!

Typical usage scenarios of multiple data sources

  1. Complex business (large amount of data): If the business is complex, it needs to be split, and the accompanying databases are also split, which involves multiple databases.
  2. Read and write separation: In order to solve the problem of quiet database read performance (both are higher than write performance, write locks will affect read blocking, thus affecting read performance)

General idea of ​​multi-data source configuration

In the case of a single data source, just getConnection to get the connection.
Single database connection diagram
The idea of ​​​​configuring multiple data sources is to make a judgment when getting the connection, which database Connection to get.
Multiple database source connection instructions

Simple example

Mainly to demonstrate the logic of switching between multiple data sources.

  1. First import the dependencies (normal springboot, mybatis dependencies) and configure yml/properties
spring:
  datasource1:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xxx_database1?serverTimezone=Asia/Shanghai
    username: xxx
    password: xxx
  datasource2:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xxx_database2?serverTimezone=Asia/Shanghai
    username: xxx
    password: xxx

Then register the datasource of the connected database with spring

@Configuration
public class DataSourceConfig {
    
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1(){
    
    
        //底层会自动拿spring.datasource.datasource1的配置,然后创建一个DataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2(){
    
    
        return DruidDataSourceBuilder.create().build();
    }
}

Finally, write a DynamicDataSource. Inheriting DataSource and
overriding DataSource require rewriting many methods. Only one is given here.

@Component
@Primary //因为注册了很多DataSource,spring不知道要找哪个dataSource,所以用primary注解告诉服务器,主要进这个DataSource
public class DynamicDataSource implements DataSource {
    
    
    @Resource
    private DataSource dataSource1;
    @Resource
    private DataSource dataSource2;
    @Override
    public Connection getConnection() throws SQLException {
    
    
    	/*
    	这里写判断进入哪个数据库的逻辑,比如说dataSource1是写库,dataSource2是读库
		可以在Controller里进行判断是读还是写,然后把他存到ThreadLocal里
		然后在这里拿出ThreadLocal的值,做if else判断,从而拿到不同的数据库
    	*/
    	if(xxx){
    
    
        	return dataSource1.getConnection();
        }else{
    
    
			return dataSource2.getConnection();
		}
    }
}

This is the general idea of ​​configuring multiple data sources and taking them to the database, but it is not the final implementation.

Spring configures the interface for accessing different databases-AbstractRoutingDataSource()

The function of this interface is to tell it which database I want to access, and then it will select the correct one from the database source for direct access. The general logic is: In fact, it is similar to the demo logic written by
our
Logical description of ARDS
byte above. It is configured inside All data sources and default data sources are obtained, and then we give a data source identifier when calling, it will find the data source we need in all data sources, and then getConnection returns to us for use and rewrites it
. so:

@Component
@Primary //将该bean设置为主要返回bean
public class DynamicDataSource extends AbstractRoutingDataSource {
    
    

    public static ThreadLocal<String> name = new ThreadLocal<>();

    @Resource
    private DataSource dataSource1;
    @Resource
    private DataSource dataSource2;
    /**
     * 用于返回当前数据源标识
     * @return {@link Object}
     */
    @Override
    protected Object determineCurrentLookupKey() {
    
    
        return name.get();
    }

    /**
     * 给
     * targetDataSources 所有数据源
     * defaultTargetDataSource 默认数据源
     * 赋值
     */
    @Override
    public void afterPropertiesSet() {
    
    
        //为targetDataSource附上所有数据源
        Map<Object,Object> targetDataSources = new HashMap<>();
        targetDataSources.put("main",dataSource1);
        targetDataSources.put("plus",dataSource2);
        super.setTargetDataSources(targetDataSources);
        //为defaultDataSource附上默认数据源
        super.setDefaultTargetDataSource(dataSource1);
        super.afterPropertiesSet();
    }
}

At this time, we can directly assign a value to the name of DynamicDataSource to complete the database switch.

@GetMapping("test")
public void test(){
    
    
	DynamicDataSource.name.set("main");
	//数据库操作
}

This is the basic method of using multiple data sources switching based on AOP!

Guess you like

Origin blog.csdn.net/qq_67548292/article/details/131735896