1. 程式人生 > >springboot+mybatis+druid 多資料來源整合

springboot+mybatis+druid 多資料來源整合

       前言:在上一篇文章裡面我們進行了spring boot 和 mybatis 的整合 《springboot整合mybatis使用druid資料來源》, 文中是使用的單資料來源,因為專案中有很多需要用到多資料來源的場景,比如主從同步(讀寫分離), 或者業務庫拆分等,這樣就需要操作不同的資料庫,所以,整合多資料來源就很有必要了。  

       網上關於 spring boot mybatis druid 多資料來源的文章很多,我這裡也借鑑了不少,不過也踩過各種坑,所以我在這裡會將詳細步驟和注意事項儘量描述清楚,希望能給需要的朋友提供一點思路和幫助。

      一:開發環境: spring boot 1.5.7.RELEASE    springboot-mybatis 1.3.2   druid-spring-boot-starter 1.1.5  mysql 5.7 系列

      二:spring boot 和 mybatis 、druid整合我這裡不再贅述,參考我上一篇文章,下面直接開始多資料來源的整合。

      2.1:首先配置檔案 application.yml 需要更改內容,增加多資料來源 one 和 two

server:
  port: 8088
  context-path: /yjbj

## 配置資料來源相關資訊
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      ## 連線池配置
      filters: stat
      maxActive: 20
      initialSize: 1
      maxWait: 60000
      minIdle: 1
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 300000
      validationQuery: select 'x'
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true
      maxOpenPreparedStatements: 20
      one:
        ## 資料來源one配置
        name: DBconfig1
        url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false
        username: ***
        password: ******
        driver-class-name: com.mysql.jdbc.Driver
      two:
        ## 資料來源two配置
        name: DBconfig2
        url: jdbc:mysql://127.0.0.1:3306/slave?useUnicode=true&characterEncoding=utf8&useSSL=false
        username: ***
        password: ******
        driver-class-name: com.mysql.jdbc.Driver
  redis:
    host: 127.0.0.1  # redis服務所在的地址
    port: 6379
    password:   # redis的密碼預設為空
    pool:
      max-active: 8  #連線池最大連線數(使用負值表示沒有限制)
      max-idle: 8  #連線池最大空閒數
      min-idle: 1  #連線池最小空閒數
      max-wait: 60000  #獲取連線的超時等待事件
    timeout: 30000  #連線redis伺服器的最大等待時間
  druid: #druid監控頁面使用者名稱和密碼
    name: admin
    pass: sailing123

## 該配置節點為獨立的節點
mybatis:
  mapper-locations: classpath:mapperXML/*.xml  # 注意:一定要對應mapper對映xml檔案的所在路徑
  config-location: classpath:MybatisConfig.xml # 注意: mybatis的配置檔案
  type-aliases-package: com.sailing.springbootmybatis.bean # 注意:對應實體類的路徑

## 配置mybatis分頁外掛
pagehelper:
  helperDialect: mysql
  reasonable: true
  support-methods-arguments: true
  params: count=conutSql

       2.2:編寫資料來源的配置類,這裡有兩個資料來源,所以需要兩個配置類,DataSourceOneConifg 和 DataSourceTwoConifg,內容分別如下:

package com.sailing.springbootmybatis.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
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.boot.context.properties.ConfigurationProperties;
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 javax.sql.DataSource;

/**
 * @author baibing
 * @project: springboot-mybatis
 * @package: com.sailing.springbootmybatis.config
 * @Description: one資料來源配置類
 * @date 2018/10/18 17:05
 */
@Configuration
//下面的sqlSessionTemplateRef 值需要和生成的SqlSessionTemplate bean name相同,如果沒有指定name,那麼就是方法名
@MapperScan(basePackages = {"com.sailing.springbootmybatis.mapper.one"}, sqlSessionTemplateRef = "sqlSessionTemplateOne")
public class DataSourceOneConfig {

    @Value("${mybatis.mapper-locations}")
    private String mapper_location;

    @Value("${mybatis.config-location}")
    private String mybatis_config;

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

    @Primary
    @Bean(name = "datasourceOne")
    @ConfigurationProperties(prefix = "spring.datasource.druid.one")
    public DataSource datasourceOne() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("datasourceOne") DataSource dataSource) throws Exception {
        logger.info("mapper檔案地址:" + mapper_location);
        logger.info("mybatis配置檔案地址:" + mybatis_config);
        //在基本的 MyBatis 中,session 工廠可以使用 SqlSessionFactoryBuilder 來建立。
        // 而在 MyBatis-spring 中,則使用SqlSessionFactoryBean 來替代:
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //如果重寫了 SqlSessionFactory 需要在初始化的時候手動將 mapper 地址 set到 factory 中,否則會報錯:
        //org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapper_location));
        bean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(mybatis_config));
        return bean.getObject();
    }

    /**
     * SqlSessionTemplate 是 SqlSession介面的實現類,是spring-mybatis中的,實現了SqlSession執行緒安全
     *
     * @param sqlSessionFactory
     * @return
     */
    @Bean
    public SqlSessionTemplate sqlSessionTemplateOne(@Qualifier("sqlSessionFactoryOne") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        return template;
    }
}
package com.sailing.springbootmybatis.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
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.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * @author baibing
 * @project: springboot-mybatis
 * @package: com.sailing.springbootmybatis.config
 * @Description: two資料來源配置類
 * @date 2018/10/18 17:28
 */
@Configuration
@MapperScan(basePackages = {"com.sailing.springbootmybatis.mapper.two"}, sqlSessionTemplateRef = "sqlSessionTemplateTwo")
public class DataSourceTwoConfig {

    @Value("${mybatis.mapper-locations}")
    private String mapper_location;

    @Bean(name = "dataSourceTwo")
    @ConfigurationProperties(prefix = "spring.datasource.druid.two")
    public DataSource dataSourceTwo() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryTwo(@Qualifier("dataSourceTwo") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //如果重寫了 SqlSessionFactory 需要在初始化的時候手動將 mapper 地址 set到 factory 中,否則會報錯:
        //org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapper_location));
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateTwo(@Qualifier("sqlSessionFactoryTwo") SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        return template;
    }
}

       注意事項:

  • 兩個資料來源各自的 @ConfigurationProperties 中的 prefix 需要和配置檔案中的一致。
  • mapperScan 中掃描 mapper 介面的路徑需要和各自介面的路徑一致,sqlSessionTemplateRef 的值需要和各自配置類中例項化的 sqlSessionTemplate 例項名一樣,如果沒有指定例項名,那麼預設就是方法名
  • 多資料來源必須要使用 @Primary 指定一個主資料來源
  • 因為我們手動建立了 SqlSessionFactory例項,所以需要將 mapper 檔案的地址和 mybatis 配置檔案的地址手動新增到 sqlSessionFactory 例項中去,這點是特別需要注意的,要不後面訪問資料庫的時候會報錯:Invalid bound statement (not found),另外:mapper檔案必須在各自資料來源中都要配置,但是mybatis配置檔案只需要在一個裡面配置就可以。
  • 多資料來源訪問的時候,訪問主資料來源只會初始化主資料來源,訪問非主資料來源的話,會將主資料來源一併初始化。

    三:編寫程式碼

    在 mapper 資料夾 one 和 two 包下建立個各自的mapper介面,注意和 mapper.xml中 namespace 對應起來,編寫各自的service 和 serviceImpl 以及controller,最終目錄如下:

    四:啟動專案進行測試:

@SpringBootApplication
public class SpringbootMybatisApplication implements CommandLineRunner{

	@Autowired
	@Qualifier("datasourceOne")
	private DataSource dataSource;

	public static void main(String[] args) {
		SpringApplication.run(SpringbootMybatisApplication.class, args);
	}

	@Override
	public void run(String... strings) throws Exception {
		System.out.println(dataSource);
	}
}


 

訪問不同的mapper介面,自動呼叫相應的資料來源。

五:最後我們登陸到druid監控系統檢視,可以看到確實建立了兩個資料來源:

 

結束:專案已經託管到 github:並且已經整合 redis + swagger2 + websocket + 自定義註解實現log日誌,這次加上多資料來源,以後有時間再加上分散式事務,喜歡的朋友給個star  ===》   https://github.com/KingOfMonkey/springboot-mybatis

csdn土豪朋友請從此處下載:https://download.csdn.net/download/white_ice/10732352

不對之處,希望大家指正。