1. 程式人生 > >Spring Boot筆記之多資料來源(Mysql+MyBatis)

Spring Boot筆記之多資料來源(Mysql+MyBatis)

Mysql+MyBatis多資料來源配置

SpringBoot單資料來源配置

pom.xml

在pom.xml中新增相關依賴:

MySQL驅動

<dependency>
	<groupId>mysql</groupId>
	<
artifactId
>
mysql-connector-java</artifactId> <version>6.0.6</version> </dependency>

SpringBoot對MyBatis的整合

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>${mybatis.spring.boot.starter.version}</
version
>
</dependency>

阿里出得一個druid,據說效能很好,不是生產環境與可以不引入

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>${druid.version}</version>
</dependency>

application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/demo?useUnicode=
true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&autoReconnect=true&failOverReadOnly=false&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 mybatis: mapper-locations: classpath:mapper/*/*.xml configuration: map-underscore-to-camel-case: true use-generated-keys: true default-fetch-size: 100 default-statement-timeout: 300

如此即可,單資料來源配置完畢,將Mapper.xml扔到classpath:mapper下面,實體、Example和mapper介面跟隨公司習慣隨便放。

SpringBoot多資料來源配置

修改application.yml

單純的使用yml檔案已經不能滿足多資料來源的配置,沿襲單資料來源的配置項和結構,在spring.datasource後增加一級以區分不同資料來源:

spring:
  datasource:
    project:
      url: jdbc:mysql://localhost:3306/demo?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&autoReconnect=true&failOverReadOnly=false&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&serverTimezone=Hongkong
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
      initialSize: 5
      minIdle: 5
      maxActive: 20
      maxWait: 60000
      timeBetweenEvictionRunsMillis: 60000
      validationQuery: SELECT 1
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true
      maxPoolPreparedStatementPerConnectionSize: 20
    exchange:
      jdbc-url: jdbc:mysql://localhost:3306/exchange?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&serverTimezone=Hongkong
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver

說明

  • project是專案的名字,exchange是另一個專案的名字,此處是兩個資料來源的名稱。
  • spring.datasource.project.urlspring.datasource.exchange.jdbc-url是不同的兩種配置,其中名為project的資料來源會使用com.alibaba.druid.pool.DruidDataSource,配置比較複雜(後面講),而名為exchange的資料來源使用com.zaxxer.hikari.HikariDataSource,配置相對簡單。

Configuration類配置

yml不能自動配置多資料來源,需要用@Configuration進行配置

首先是比較簡單的HikariDataSource

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.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.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "one.hht.api.exchange", sqlSessionTemplateRef = "exchangeSqlSessionTemplate")
public class ExchangeDataSourceConfiguration {
    @Bean(name = "exchangeDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.exchange")
    public DataSource exchangeDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "exchangeSqlSessionFactory")
    @Primary
    public SqlSessionFactory exchangeSqlSessionFactory(@Qualifier("exchangeDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/exchange/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "exchangeDataSourceTransactionManager")
    @Primary
    public DataSourceTransactionManager exchangeDataSourceTransactionManager(@Qualifier("exchangeDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "exchangeSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate exchangeSqlSessionTemplate(@Qualifier("exchangeSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

然後是DruidDataSource的配置

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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "one.hht.api.project", sqlSessionTemplateRef = "projectSqlSessionTemplate")
public class ProjectDataSourceConfiguration {
    @Autowired
    private DataSourceProperties properties;

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

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

    @Value("${spring.datasource.project.maxActive}")
    private Integer maxActive;

    @Value("${spring.datasource.project.maxWait}")
    private Integer maxWait;

    @Value("${spring.datasource.project.timeBetweenEvictionRunsMillis}")
    private Integer timeBetweenEvictionRunsMillis;

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

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

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

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

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

    @Value("${spring.datasource.project.maxPoolPreparedStatementPerConnectionSize}")
    private Integer maxPoolPreparedStatementPerConnectionSize;

    @Bean(name = "projectDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.project")
    public DataSource projectDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(properties.getUrl());
        dataSource.setUsername(properties.getUsername());
        dataSource.setPassword(properties.getPassword());
        dataSource.setDriverClassName(properties.getDriverClassName());
        dataSource.setInitialSize(initialSize);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxActive(maxActive);
        dataSource.setMaxWait(maxWait);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestOnReturn(testOnReturn);
        dataSource.setPoolPreparedStatements(poolPreparedStatements);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        return dataSource;
    }

    @Bean(name = "projectSqlSessionFactory")
    @Primary
    public SqlSessionFactory projectSqlSessionFactory(@Qualifier("projectDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/project/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "projectDataSourceTransactionManager")
    @Primary
    public DataSourceTransactionManager projectDataSourceTransactionManager(@Qualifier("projectDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "projectSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate projectSqlSessionTemplate(@Qualifier("projectSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

結語

如此配置,將mapper介面放到相應的basePackages指定包中,mapper.xml放到MapperLocations指定路徑下,即可。。。

兩種配置方法個人感覺還是用com.alibaba.druid.pool.DruidDataSource的這種比較靠譜。