Springbootで複数のデータソースを設定する【詳しい解説】

はじめに、データ ソースおよびデータベース接続プールとは何ですか

SpringBoot のマルチデータ ソース構成について説明する前に、まず DataSource について理解しましょう。
Java では、データベースを操作するさまざまな方法があり、JDBC に加えて、さまざまな方法で DataSource オブジェクトが存在します。

DataSource はデータ ソースとみなすことができます。
データベース パラメータをカプセル化し、データベースに接続し、プログラム内で DataSource オブジェクトを操作してデータベースの追加、削除、変更、クエリを実行します。

メソッドごとに使用される DataSource オブジェクトは異なります。以下に記載されています:

dbcp フレームワークの DataSource クラスは: org.apache.commons.dbcp.BasicDataSource
c3p0 フレームワークの DataSource クラスは: com.mchange.v2.c3p0.ComboPooledDataSource
MyBatis フレームワークの DataSource クラスは: org.apache.ibatis .datasource.pooled.PooledDataSource
Druid フレームワークの DataSource クラスは、com.alibaba.druid.pool.DruidDataSource です。

DataSource の一部の実装では、データベース接続プールと呼ばれることがよくあります

例えば、Druid の公式ドキュメントには「Druid は Java 言語で最高のデータベース接続プールである」と記載されていますが、実現されているのはコアの構築のみで、コア上に多くの周辺の構築が構築されています。

データ ソースとデータベース接続プールの関係は次のとおりです。

  • データ ソースは複数のデータベース接続を確立し、データベース接続プールに保存されます。
  • データベースにアクセスする必要がある場合、データベース接続プールからアイドル状態のデータベース接続を取得するだけで済みます。
  • プログラムがデータベースへのアクセスを終了すると、データベース接続はデータベース接続プールに戻されます。

JDBC の学習を開始した当初、自分でデータ接続を取得する操作は次のとおりです。
ここに画像の説明を挿入
JDBC を学習する場合、DriverManager フォームを直接使用するには、通常、ドライバーをプロジェクトにハードコーディングする必要があります (JDBC4.0 以降はドライバーを自動的に登録できます)。 。

そして最も重要なことは、DriverManager の getConnection メソッドを通じて取得される接続であり、データベースとの接続を確立します。

ただし、データベースとの接続の確立はリソースを大量に消費するタスクであり、データベース接続を頻繁に確立すると、大きなシステム オーバーヘッドが発生します。

DataSource で取得される接続は接続プールから取得されますが、プール内の接続は基本的に DriverManager から取得されます。

DataSource は DriverManager の代替の役割であり、外部接続を提供する機能があります。

次に、SpringBoot が複数のデータ ソースをどのように統合するかを見てみましょう。

1. 構成ファイルを構成します。

1. 依存関係をインポートします。

新しいデータベースのデータ ソースが現在のデータベースと異なる場合は、MySQL や PGSQL などの新しいデータベースのドライバー依存関係を忘れずに導入してください。

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>
 
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.7</version>
</dependency>

まず、構成ファイルで複数のデータ ソースの接続情報を構成する必要があります。

ここでは yml 構成ファイルが使用されており、他のタイプの構成ファイルも同じです。2
つのデータ ソースを構成しました。1 つは ds1 データ ソースという名前で、もう 1 つは ds2 データ ソースという名前です。さらにデータ ソースを構成したい場合は、そのまま続行してください。それらを追加します。

spring:
 # 数据源配置
  datasource:
    ds1: #数据源1
      driver-class-name: com.mysql.jdbc.Driver # mysql的驱动你可以配置别的关系型数据库
      url: jdbc:mysql://ip:3306/db1 #数据源地址
      username: root # 用户名
      password: root # 密码
    ds2: # 数据源2
      driver-class-name: com.mysql.jdbc.Driver # mysql的驱动你可以配置别的关系型数据库
      url: jdbc:mysql://ip:3307/db2#数据源地址
      username: root # 用户名
      password: root # 密码

2. 構成クラスを作成します。

Springboot の構成クラスを作成します。

mybatis マルチデータ ソース スイッチングの原理は、異なるパッケージに従って異なるデータ ソースを呼び出すことです。

パッケージにmapper.javaとmapper.xmlを記述するだけで、springbootが自動的にデータソースを切り替えます。

コアコードは次の 2 つの文だけです。

1. パッケージのスキャンを指定するために使用され、sqlSessionTemplateRef を指定します

@MapperScan(basePackages ="com.web.ds2.**.dao", 
            sqlSessionTemplateRef = "ds2SqlSessionTemplate")

2、mapper.xml のパスを指定するために使用されます。

sqlSessionFactory.
    setMapperLocations(new PathMatchingResourcePatternResolver().
                                getResources("classpath*:com/web/ds2/**/*.xml"));

詳細なコードは次のとおりです。

3. Mybatis メイン データ ソース ds1 構成:

/**
 * Mybatis主数据源ds1配置
 * 多数据源配置依赖数据源配置
 * @see  DataSourceConfig
 */
@Configuration
@MapperScan(basePackages ="com.web.ds1.**.dao", sqlSessionTemplateRef  = "ds1SqlSessionTemplate")
public class MybatisPlusConfig4ds1 {
    
    
 
    @Bean(name = "dataSource1")
    @ConfigurationProperties(prefix = "spring.datasource.ds1")
    @Primary
    public DataSource dataSource() {
    
    
        return DataSourceBuilder.create().build();
    }
 
    //主数据源 ds1数据源
    @Primary
    @Bean("ds1SqlSessionFactory")
    public SqlSessionFactory ds1SqlSessionFactory(@Qualifier("ds1DataSource") DataSource dataSource) throws Exception {
    
    
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().
                        getResources("classpath*:com/web/ds1/**/*.xml"));  
        return sqlSessionFactory.getObject();
    }
 
    @Primary
    @Bean(name = "ds1TransactionManager")
    public DataSourceTransactionManager ds1TransactionManager(@Qualifier("ds1DataSource") DataSource dataSource) {
    
    
        return new DataSourceTransactionManager(dataSource);
    }
 
    @Primary
    @Bean(name = "ds1SqlSessionTemplate")
    public SqlSessionTemplate ds1SqlSessionTemplate(@Qualifier("ds1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
    
    
        return new SqlSessionTemplate(sqlSessionFactory);
    }
 
}

4. Mybatis の 2 番目の ds2 データ ソース構成:

/**
 * Mybatis  第二个ds2数据源配置
 * 多数据源配置依赖数据源配置
 * @see  DataSourceConfig
 */
@Configuration
@MapperScan(basePackages ="com.web.ds2.**.dao", sqlSessionTemplateRef  = "ds2SqlSessionTemplate")
public class MybatisPlusConfig4ds2 {
    
    
 
    @Bean(name = "dataSource2")
    @ConfigurationProperties(prefix = "spring.datasource.ds2")
    public DataSource dataSource() {
    
    
        return DataSourceBuilder.create().build();
    }
 
    //ds2数据源
    @Bean("ds2SqlSessionFactory")
    public SqlSessionFactory ds2SqlSessionFactory(@Qualifier("ds2DataSource") DataSource dataSource) throws Exception {
    
    
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().
                getResources("classpath*:com/web/ds2/**/*.xml"));
        return sqlSessionFactory.getObject();
    }
 
    //事务支持
    @Bean(name = "ds2TransactionManager")
    public DataSourceTransactionManager ds2TransactionManager(@Qualifier("ds2DataSource") DataSource dataSource) {
    
    
        return new DataSourceTransactionManager(dataSource);
    }
 
    @Bean(name = "ds2SqlSessionTemplate")
    public SqlSessionTemplate ds2SqlSessionTemplate(@Qualifier("ds2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
    
    
        return new SqlSessionTemplate(sqlSessionFactory);
    }
 
}

5. Mybatis 3 番目のデータ ソース構成 (別の構成方法):

DataSourceTransactionManager トランザクション管理があります

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 
import javax.sql.DataSource;
 
@Configuration
@EnableJpaRepositories({
    
    "xxx.xxx.xx.xx.xx"})
@MapperScan(basePackages = {
    
    "xx.xx.xx.xx.xx.xx"}, sqlSessionFactoryRef = "sqlSessionFactory")
public class PrimaryDataSourceConfig {
    
    
 
    @Bean
    @ConfigurationProperties(prefix = "mybatis-plus.configuration")
    public MybatisConfiguration globalConfiguration() {
    
    
        return new MybatisConfiguration();
    }
 
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    @Primary
    public DataSource dataSource() {
    
    
        return DataSourceBuilder.create().build();
    }
 
    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
    
    
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //这里将下划线映射为驼峰的配置引入
        bean.setConfiguration(globalConfiguration());
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml"));
        return bean.getObject();
    }
 
    @Bean(name = "transactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
    
    
        return new DataSourceTransactionManager(dataSource);
    }
 
    @Bean(name = "sqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
    
    
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

6. コードの説明:

  • @ConfigurationProperties(prefix = "spring.datasource.ds1"): spring.datasource.ds1 で始まる構成を使用します。
  • @Qualifier: 主にインジェクションが成功することを保証するために、Bean の name 属性と同じデータ ソース名を指定します。
  • @Primary: これがプライマリ データ ソース (デフォルト データ ソース) であることを宣言します。これは複数のデータ ソース構成に不可欠です。
  • @Qualifier: 受信 Bean を明示的に選択します。

7. 注意事項:

スキャンされた Mapper パスは 2 つのデータ ソースで構成されているため、以前に SpringBoot スタートアップ クラスで Mapper スキャン アノテーションを使用していた場合は、それらを削除する必要があります。

3. テストして使用します。

サービス層:

@Service
public class TestService {
    
    
 
    @Resource
    private ClusterMapper clusterMapper;
    @Resource
    private MasterMapper masterMapper;
 
    public List<HashMap<String, Object>> queryBooks() {
    
    
        return masterMapper.queryBooks(); //指定的配置类扫描的是一个包
    }
 
    public List<HashMap<String, Object>> queryOrders() {
    
    
        return clusterMapper.queryOrders(); //指定的配置类扫描的是另一个包
    }
}

コントローラー層:

@RestController
@RequestMapping(value = "/test", method = RequestMethod.POST)
public class TestController {
    
    
    @Resource
    private TestService testService;
 
    @RequestMapping("/books")
    public List<HashMap<String, Object>> queryBooks() {
    
    
        return testService.queryBooks();
    }
 
    @RequestMapping("/orders")
    public List<HashMap<String, Object>> queryOrders() {
    
    
        return testService.queryOrders();
    }
}

5.拡張(ドルイドの統合)

接続プール:

実際、複数のデータ ソースの変換では、通常、デフォルトの JDBC 接続方法は使用されず、多くの場合、接続の最適化のために接続プールを導入する必要があります。そうしないと、データ ソース接続が切断されるなどのエラー ログが頻繁に発生する可能性があります。

実際、データ ソースで接続プール データ ソースを切り替え、接続プールの依存関係を直接導入し、dataSource の作成部分を接続プール データ ソースの作成に置き換えることは非常に簡単です。

Ali の Druid を例として、まず接続プールのデータ ソースの依存関係を紹介します。

依存関係をインポートする

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
</dependency>

設定ファイルに、Druid のいくつかの設定を追加します。

spring.datasource.datasource2.initialSize=3 # 根据自己情况设置
spring.datasource.datasource2.minIdle=3
spring.datasource.datasource2.maxActive=20

dataSource Bean の作成コード部分を書き換えます。

/**
 * Mybatis  第二个ds2数据源配置
 * 多数据源配置依赖数据源配置
 * @see  DataSourceConfig
 */
@Configuration
@MapperScan(basePackages ="com.web.ds2.**.dao", sqlSessionTemplateRef  = "ds2SqlSessionTemplate")
public class MybatisPlusConfig4ds2 {
    
    
 
    @Value("${spring.datasource.datasource2.jdbc-url}")
    private String url;
    @Value("${spring.datasource.datasource2.driver-class-name}")
    private String driverClassName;
    @Value("${spring.datasource.datasource2.username}")
    private String username;
    @Value("${spring.datasource.datasource2.password}")
    private String password;
    @Value("${spring.datasource.datasource2.initialSize}")
    private int initialSize;
    @Value("${spring.datasource.datasource2.minIdle}")
    private int minIdle;
    @Value("${spring.datasource.datasource2.maxActive}")
    private int maxActive;
 
    @Bean(name = "dataSource2")
    public DataSource dataSource() {
    
    
    	//用druid要 new DruidDataSource() 实现类,Spring Boot 默认是不注入druid这些属性值的,需要自己绑定
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setInitialSize(initialSize);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxActive(maxActive);
        return dataSource;
    }
 
    //...
 
}

上記の書き換えられた dataSource 構成クラス コードで、データ ソース接続プロパティの参照を設定します。パス構造に注意してください必要に応じて設定します

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 连接池类型:使用druid
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

依存関係をインポートする

<!-- 使用Druid产生的日志功能log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

DruidConfig クラスを作成し、その監視機能を使用する

package com.rui.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.HashMap;

@Configuration
public class DruidConfig {
    
    

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource(){
    
    
        return new DruidDataSource();
    }

    //后台监控功能 :web.xml  ServletRegistrationBean
    //因为SpringBoot 内置了servlet容器,所以没有web.xml, 替代方法ServletRegistrationBean
    //Druid 数据源具有监控的功能,并提供了一个 web 界面方便用户查看,类似安装 路由器 时,人家也提供了一个默认的 web 页面。
    @Bean
    public ServletRegistrationBean statViewServlet(){
    
    
        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");

        HashMap<String, String> initParameter = new HashMap<>();
        //增加配置
        initParameter.put("loginUsername","admin");
        initParameter.put("loginPassword","123456");
        //允许谁可以访问
        initParameter.put("allow","");
        //deny:Druid 后台拒绝谁访问
        //initParams.put("rui", "192.168.1.20");表示禁止此ip访问
        //设置初始化参数
        bean.setInitParameters(initParameter);

        return bean;
    }

    //配置 Druid 监控 之  web 监控的 filter//WebStatFilter:用于配置Web和Druid数据源之间的管理关联监控统计
    @Bean
    public FilterRegistrationBean webStatFilter(){
    
    
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        HashMap<String, String> initParameter = new HashMap<>();
        //这些东西不进行统计
        initParameter.put("exclusions","*.js,*.css,/druid/*");
        //设置初始化参数
        bean.setInitParameters(initParameter);
        return bean;

    }

}

以下にアクセスすることを選択するhttp://localhost:8080/druid/login.htmlと、その強力な監視機能を確認できます。

完全な構成 (コピーを使用可能)

1. プロジェクト設定ファイル

druid: 
  mysql: 
  # mysql仅仅配置validateQuery是不行的,还要配置usePingMethod来检测连接池中的连接是否可用
  usePingMethod: false
  
# 第一数据源配置(Postgresql)
spring:
  datasource:
    # 连接池类型:使用druid
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.postgresql.Driver
    username: root
    password: 123456
    url: jdbc:postgresql://ip:端口/数据库名
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 1
    minIdle: 3
    maxActive: 20
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 连接超时不再无限重复获取
    removeAbandoned: true
    # 跳过连接超时时间
    removeAbandonedTimeout: 60
    # 关闭连接超时异常日志
    logAbandoned: true
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 'X'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,slf4j
    # 打开PSCache,并且指定每个连接上PSCache的大小(本质上就是缓存游标)
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 合并多个DruidDataSource的监控数据
    useGlobalDataSourceStat: true
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  
# 第二数据源配置(mysql)
slave2:
  datasource:
    # 连接池类型:使用druid
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://ip:端口/数据库名?useUnicode=true&characterEncoding=utf8&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 1
    minIdle: 3
    maxActive: 100
    # 配置获取连接等待超时的时间
    maxWait: 60000
    # 连接超时不再无限重复获取
    removeAbandoned: true
    # 跳过连接超时时间
    removeAbandonedTimeout: 60
    # 关闭连接超时异常日志
    logAbandoned: true
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 'X'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,slf4j
    # 打开PSCache,并且指定每个连接上PSCache的大小(本质上就是缓存游标)
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 合并多个DruidDataSource的监控数据
    useGlobalDataSourceStat: true
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

2. 構成クラス

package com.xxx.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;

@Configuration
@MapperScan(basePackages = MasterDruidDBConfig.PACKAGE ,sqlSessionTemplateRef = "masterSqlSessionTemplate")
@Primary//在同样的DataSource中,首先使用被标注的DataSource
public class MasterDruidDBConfig {
    
    
	//扫描dao路径
	static final String PACKAGE = "com.xxx.*.masterdao";
	//扫描mapper路径
	static final String MAPPER_LOCATION = "classpath:mapper/*/master/*.xml";
	
    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${spring.datasource.initialSize}")
    private int initialSize;

    @Value("${spring.datasource.minIdle}")
    private int minIdle;

    @Value("${spring.datasource.maxActive}")
    private int maxActive;
    //配置获取连接等待超时的时间

    @Value("${spring.datasource.maxWait}")
    private Long maxWait;
    //配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

    @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
    private Long timeBetweenEvictionRunsMillis;
    //配置一个连接在池中最小生存的时间,单位是毫秒

    @Value("${spring.datasource.minEvictableIdleTimeMillis}")
    private Long minEvictableIdleTimeMillis;

    @Value("${spring.datasource.validationQuery}")
    private String validationQuery;

    @Value("${spring.datasource.testWhileIdle}")
    private Boolean testWhileIdle;

    @Value("${spring.datasource.testOnBorrow}")
    private Boolean testOnBorrow;

    @Value("${spring.datasource.testOnReturn}")
    private Boolean testOnReturn;
    //打开PSCache,并且指定每个连接上PSCache的大小

    @Value("${spring.datasource.poolPreparedStatements}")
    private Boolean poolPreparedStatements;

    @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
    private int maxPoolPreparedStatementPerConnectionSize;
    //配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙

    @Value("${spring.datasource.filters}")
    private String filters;
    //通过connectProperties属性来打开mergeSql功能;慢SQL记录

    @Value("${spring.datasource.connectionProperties}")
    private String connectionProperties;
    //合并多个DruidDataSource的监控数据
    //useGlobalDataSourceStat: true

    //连接超时不再无限重复获取
    @Value("${spring.datasource.removeAbandoned}")
    private Boolean removeAbandoned;

    //跳过连接超时时间
    @Value("${spring.datasource.removeAbandonedTimeout}")
    private int removeAbandonedTimeout;

    //关闭连接超时异常日志
    @Value("${spring.datasource.logAbandoned}")
    private Boolean logAbandoned;

    private Logger logger = LoggerFactory.getLogger(MasterDruidDBConfig.class);


    @Bean(name = "masterDataSource", initMethod = "init", destroyMethod = "close")
    //@ConfigurationProperties(prefix = "spring.datasource.master")
    @Primary//在同样的DataSource中,首先使用被标注的DataSource
    public DataSource dataSource() {
    
    
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setDriverClassName(driverClassName);
        //configuration
        druidDataSource.setInitialSize(initialSize);
        druidDataSource.setMinIdle(minIdle);
        druidDataSource.setMaxActive(maxActive);
        druidDataSource.setMaxWait(maxWait);
        druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        druidDataSource.setValidationQuery(validationQuery);
        druidDataSource.setTestWhileIdle(testWhileIdle);
        druidDataSource.setTestOnBorrow(testOnBorrow);
        druidDataSource.setTestOnReturn(testOnReturn);
        druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
    
    
            druidDataSource.setFilters(filters);
        } catch (SQLException e) {
    
    
            logger.error("druid configuration initialization filter", e);
        }
        druidDataSource.setConnectionProperties(connectionProperties);
        return druidDataSource;
    }

    @Bean(name = "masterSqlSessionFactory")
    @Primary //在同样的DataSource中,首先使用被标注的DataSource
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
    
    
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MasterDruidDBConfig.MAPPER_LOCATION));

        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        // 自动使用驼峰命名属性映射字段 userId -> user_id
        configuration.setMapUnderscoreToCamelCase(true);
        sessionFactory.setConfiguration(configuration);

        return sessionFactory.getObject();
    }

    @Bean(name = "masterTransactionManager")
    @Primary//在同样的DataSource中,首先使用被标注的DataSource
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
    
    
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "masterSqlSessionTemplate")
    @Primary//在同样的DataSource中,首先使用被标注的DataSource
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    
    
        return new SqlSessionTemplate(sqlSessionFactory);
    }

}

提案:
建议去使用mybatis-plus 集成 多数据源。

構成の概要については、こちらをご覧ください --> springboot は druid マルチデータ ソース構成を統合します

おすすめ

転載: blog.csdn.net/qq_27480007/article/details/130736925