springboot+druid+mybatis配置多数据源同时生效 – 配置多数据源(一)

应用场景

  • 多数据源对应的表可能不同
  • 每个数据库维护自己的数据
  • 每个数据源维护自己对应的mapper
  • 本质上是一连多,并没有切换数据源

实现

引入依赖

环境为springboot2.7.5

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- mybatis 支持 SpringBoot -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.16</version>
        </dependency>
        <!--引用 log4j2 spring boot 启动器,内部依赖了 slf4j、log4j;排除项目中的 logback-->
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
            <version>3.0.3</version>
        </dependency>
mapper和xml

分别对应不同的mapper,需要映射对应的mapper接口,person可以换成不同的实体类和表
master.xml

<mapper namespace="com.example.demo.mapper.master.PersonMapper0">

cluster.xml

<mapper namespace="com.example.demo.mapper.master.PersonMapper1">

xml文件放在对应resourcesmapping目录下

PersonMapper0.java

@Mapper //表示这是Mybatis的mapper类
@Repository
public interface PersonMapper0 {

    List<Person> queryUserList();

    Person queryUserByID(String id);

    int addUser(Person person);

    int updateUser(Person person);

    int deleteUser(String id);

}
配置文件

需要自定义两个(多个)数据源的配置项,这里只列举了基础属性

spring:
  datasource:
    db01:
      # 指定数据源
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
      # 1.jdbc配置
      url: jdbc:mysql://localhost:3306/demo1
      username: root
      password: xxxxxx
      #2.连接池配置
      #初始化连接池的连接数量 大小,最小,最大
      initial-size: 5
    db02:
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
      # 1.jdbc配置
      url: jdbc:mysql://localhost:3306/demo2
      username: root
      password: xxxxxx
      #2.连接池配置
      #初始化连接池的连接数量 大小,最小,最大
      initial-size: 5
数据库配置类

数据库连接相关,以及扫描实体和mapper

主数据库master配置类

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
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  = MasterDbConfig.PACKAGE , sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDbConfig {
    private Logger logger = LoggerFactory.getLogger(MasterDbConfig.class);
    // 精确到 master 目录,以便跟其他数据源隔离
    static final String PACKAGE = "com.example.demo.mapper.master";
    private static final String MAPPER_LOCATION = "classpath*:mapping/master/*.xml";
    private static final String DOMAIN_PACKAGE = "com.example.demo.entity";

    @Value("${spring.datasource.db01.url}")
    private String dbUrl;

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

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

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

    @Bean(name="masterDataSource")   //声明其为Bean实例
    @Primary  //在同样的DataSource中,首先使用被标注的DataSource
    public DataSource masterDataSource() {
        DruidDataSource datasource = new DruidDataSource();

        datasource.setUrl(this.dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);

        return datasource;
    }

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource());
    }

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(masterDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(MasterDbConfig.MAPPER_LOCATION));
        sessionFactory.setTypeAliasesPackage(DOMAIN_PACKAGE);
        //mybatis 数据库字段与实体类属性驼峰映射配置
        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sessionFactory.getObject();
    }
}

从数据库Cluster配置类

package com.example.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

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

/**
 * 从数据源配置
 * 若需要配置更多数据源 , 直接在yml中添加数据源配置再增加相应的新的数据源配置类即可
 */
@Configuration
@MapperScan(basePackages  = ClusterDbConfig.PACKAGE , sqlSessionFactoryRef = "clusterSqlSessionFactory")
public class ClusterDbConfig {
    private Logger logger = LoggerFactory.getLogger(ClusterDbConfig.class);
    // 精确到 cluster 目录,以便跟其他数据源隔离
    static final String PACKAGE = "com.example.demo.mapper.cluster";
    private static final String MAPPER_LOCATION = "classpath*:mapping/cluster/*.xml";
    private static final String DOMAIN_PACKAGE = "com.example.demo.entity";

    @Value("${spring.datasource.db02.url}")
    private String dbUrl;

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

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

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

    @Bean(name="clusterDataSource")   //声明其为Bean实例
    public DataSource clusterDataSource() {
        DruidDataSource datasource = new DruidDataSource();

        datasource.setUrl(this.dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        return datasource;
    }

    @Bean(name = "clusterTransactionManager")
    public DataSourceTransactionManager clusterTransactionManager() {
        return new DataSourceTransactionManager(clusterDataSource());
    }

    @Bean(name = "clusterSqlSessionFactory")
    public SqlSessionFactory clusterSqlSessionFactory(@Qualifier("clusterDataSource") DataSource culsterDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(culsterDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(ClusterDbConfig.MAPPER_LOCATION));
        sessionFactory.setTypeAliasesPackage(DOMAIN_PACKAGE);
        //mybatis 数据库字段与实体类属性驼峰映射配置
        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sessionFactory.getObject();
    }
}
测试访问

启动项目后会看到有两个datasource连接池

@CrossOrigin
@RestController
@RequestMapping("/define")
public class DemoController {
    @Autowired
    PersonMapper0 pMapperMaster;

    @GetMapping("/pMapperMaster")
    public List<Person> pMapperMaster() {
        List<Person> users = pMapperMaster.queryUserList();
        return users;
    }

    @Autowired
    PersonMapper1 pMapperCluster;

    @GetMapping("/pMapperCluster")
    public List<Person> pMapperCluster() {
        List<Person> users = pMapperCluster.queryUserList();
        return users;
    }
}
访问结果

两个数据源的数据不同

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐