前言

此文介绍的是在SpringBoot中使用Mybatis配置多数据源(多个数据库),整合Druid

网上有很多文章,翻了翻,但是都有问题啊,有的是没使用Druid,使用了默认的Hirika,有的是配置文件不给或者给的是Hirika能用的配置,层级不对,所以我自己来记一下

代码

pom文件maven依赖

	<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.9</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

yml配置文件结构

数据源配置放druid下面

不使用Druid,url就不用改成jdbc-url

使用mybatis这种方式配置,不指定线程池的话,默认的连接池是Hirika

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initialSize: 5
      minIdle: 5
      maxActive: 20
      maxWait: 60000
      datasource1:
        name: datasource1
        url: *********
        username: *********
        password: *********
        driver-class-name: *********
      datasource2:
        name: datasource2
        url: *********
        username: *********
        password: *********
        driver-class-name: *********

properties版

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.initialSize=5
spring.datasource.druid.minIdle=5
spring.datasource.druid.maxActive=20
spring.datasource.druid.maxWait=60000
spring.datasource.druid.datasource1.name=datasource1
spring.datasource.druid.datasource1.url=jdbc:mysql://ip:port/数据库名
spring.datasource.druid.datasource1.username=11
spring.datasource.druid.datasource1.password=11
spring.datasource.druid.datasource1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.datasource2.name=datasource2
spring.datasource.druid.datasource2.url=jdbc:mysql://ip:port/数据库名
spring.datasource.druid.datasource2.username=11
spring.datasource.druid.datasource2.password=11
spring.datasource.druid.datasource2.driver-class-name=com.mysql.cj.jdbc.Driver

多数据源配置类

注意,Mybatis-plus使用MybatisSqlSessionFactoryBean ,纯Mybatis使用SqlSessionFactoryBean

此类指定有多少个数据源,我配了datasource1、datasource2两个

关键点在于return的类型,网上很多配置多数据源的文章使用return DataSourceBuilder.create().build(); ,这样的话连接池是Hirika,参考DataSourceBuilder源码如下
在这里插入图片描述

1.@Bean(name = “datasource1”)

指定数据源bean的name

2.@ConfigurationProperties(prefix = “spring.datasource.druid.datasource1”)

指定读取yml中配置的路径

3.return new DruidDataSource();

指定连接池为Druid
import javax.sql.DataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
public class DataSourceConfig {

    @Bean(name = "datasource1")
    @ConfigurationProperties(prefix = "spring.datasource.druid.datasource1")
    public DataSource dataSource1() {
        return new DruidDataSource();
    }

 
    @Bean(name = "datasource2")
    @ConfigurationProperties(prefix = "spring.datasource.druid.datasource2")
    public DataSource dataSource2() {
        return new DruidDataSource();
    }
}


主数据源具体配置

这个类用来配置主数据源

1.@MapperScan(basePackages = {“com.oxye.mapper.ds1”}, sqlSessionFactoryRef = “sqlSessionFactoryDs1”)

basePackages 指定扫描mapper的路径

sqlSessionFactoryRef  关联bean sqlSessionFactoryDs1

2.@Autowired
@Qualifier(“datasource1”)
private DataSource datasource1;

指定数据源

3.@Primary

指定本数据源的SqlSessionFactory、SqlSessionTemplate、DataSourceTransactionManager为主要bean,项目启动、运行时寻找相关bean时,会使用带@Primary注解的bean,如果都不配置@Primary,系统会报错,不知选择哪个bean

4.factoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources(“classpath:/mapperDs1/*.xml”)
);

设置mapper.xml文件的路径,yml中的mybatis可以去掉

mybatis:mapper-locations:*** 了

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.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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 = {"com.ais.cdc.mapper"}, sqlSessionFactoryRef = "sqlSessionFactoryDs1")
public class MybatisMasterConfig {

    @Autowired
    @Qualifier("datasource1")
    private DataSource datasource1;

    @Bean
    @Primary
    public SqlSessionFactory sqlSessionFactoryDs1() throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(datasource1);
        factoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*.xml")
        );
        //向Mybatis过滤器链中添加拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        factoryBean.setPlugins(interceptor);
        return factoryBean.getObject();
    }

    @Bean
    @Primary
    public SqlSessionTemplate sqlSessionTemplateDs1() throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactoryDs1());
        return template;
    }

    @Bean
    @Primary
    public DataSourceTransactionManager transactionManager1() {
        return new DataSourceTransactionManager(datasource1);
    }
}

其他数据源具体配置类

和主数据源配置差不多,区别是不用设置@Primary,如果你希望主sqlSession是主数据源,事务优先使用此数据源,可以把@Primary移动到这里

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.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = {"com.ais.cdc.mapper2"}, sqlSessionFactoryRef = "sqlSessionFactoryDs2")
public class MybatisSlaveConfig {

    @Autowired
    @Qualifier("datasource2")
    private DataSource datasource2;

    @Bean
    public SqlSessionFactory sqlSessionFactoryDs2() throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(datasource2);
        factoryBean.setMapperLocations(
                //设置mybatis的xml所在位置
                new PathMatchingResourcePatternResolver().getResources("classpath:/mapper2/*.xml")
        );
        return factoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateDs2() throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactoryDs2());
        return template;
    }

    @Bean
    public DataSourceTransactionManager transactionManager2() {
        return new DataSourceTransactionManager(datasource2);
    }
}

相关问题

1.报错无jdbc-url

说明Druid没生效,使用的是默认的Hirika,所以需要jdbc-url,Druid是可以用url的

2.查看源码时发现connect是Hirika的

因为数据源应该返回return new DruidDataSource(); ,而不是

return DataSourceBuilder.create().build();

3.绑定异常 BindingException

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

看看你mapper的路径是不是配错了

4.启动创建bean冲突 UnsatisfiedDependencyException

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘***’

@Bean注解的类或方法默认使用小写开头的类名、文件名,看看是不是重复了,重复的话使用@Bean的name指定名称,注入其他bean时使用@Qualifier("***")指定bean名称

5.启动或运行时,报错找到多个bean required a single bean, but 2 were found:

***required a single bean, but 2 were found

使用@Primary指定主数据源、主事务管理器

6.Mybatis-Plus-Join拦截器未注入

找到com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration,重写这个类,手动注入拦截器,如下:

		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.getDbType(databaseIdProvider.getDatabaseId(datasource1))));
        factory.setPlugins(interceptor, new SpecialCharInterceptor(), this.interceptors[0]);

参考:

这篇配置后使用的不是Druid

springboot-mybatis配置多数据源

这篇过于实用,没解决问题

Mybatis+Druid多数据源配置

这篇较为全,但是其实没用到Druid,评论区很精彩

springboot + mybatis + druid + 多数据源

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐