この記事では、Springboot で複数のデータ ソースを構成する方法を説明しています。

複数のデータソースの一般的な使用シナリオ

  1. 複雑なビジネス (大量のデータ): ビジネスが複雑な場合は分割する必要があり、付随するデータベースも分割されるため、複数のデータベースが関係します。
  2. 読み取りと書き込みの分離: 静かなデータベース読み取りパフォーマンスの問題を解決するために (どちらも書き込みパフォーマンスよりも高いため、書き込みロックは読み取りブロックに影響し、読み取りパフォーマンスに影響します)

マルチデータソース構成の一般的な考え方

単一のデータ ソースの場合は getConnection で接続を取得するだけですが、
単一データベースの接続図
複数のデータ ソースを構成する場合は、接続を取得するときにどのデータベースの Connection を取得するかを判断する必要があります。
複数のデータベースソース接続命令

簡単な例

主に、複数のデータ ソース間で切り替えるロジックをデモンストレーションするために使用されます。

  1. まず依存関係 (通常の springboot、mybatis の依存関係) をインポートし、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

次に、接続したデータベースのデータソースを 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();
    }
}

最後に、DynamicDataSource を作成します。DataSource の継承と
DataSource のオーバーライドには、多くのメソッドを書き直す必要があります。ここでは 1 つだけ示します。

@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();
		}
    }
}

これは、複数のデータ ソースを構成してデータベースに取り込むという一般的なアイデアですが、最終的な実装ではありません。

Spring は、さまざまなデータベースにアクセスするためのインターフェイスを構成します - AbstractRoutingDataSource()

このインターフェイスの機能は、どのデータベースにアクセスしたいかを伝えることであり、その後、直接アクセスするためにデータベース ソースから正しいデータベースを選択します。一般的なロジックは次のとおりです。実際、これは、私たちが作成したデモ ロジックに似ています

ARDS の論理的説明
すべてのデータ ソースとデフォルトのデータ ソースが取得され、呼び出し時にデータ ソース識別子を指定すると、すべてのデータ ソースで必要なデータ ソースが検索され、getConnection が使用のために返されます。それを書き換えます

@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();
    }
}

この時点で、DynamicDataSource の名前に値を直接割り当てて、データベースの切り替えを完了できます。

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

AOPによる複数データソース切り替えの基本的な使い方です!

おすすめ

転載: blog.csdn.net/qq_67548292/article/details/131735896