Bootstrap

Spring Boot 多数据源配置

1. 项目结构

src
├── main
│   ├── java
│   │   └── org
│   │       └── songtang
│   │           └── springbootdynamic
│   │               ├── config
│   │               ├── controller
│   │               ├── entity
│   │               ├── mapper
│   │               │   ├── master
│   │               │   └── slave
│   │               └── service
│   └── resources
│       └── mapper
│           ├── master
│           └── slave
└── test

pom配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.2</version>
        <relativePath/>
    </parent>

    <groupId>org.songtang</groupId>
    <artifactId>springboot-dynamic</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
        <mysql.version>8.4.0</mysql.version>
        <mybatisplus.version>3.5.7</mybatisplus.version>
    </properties>

    <dependencies>
        <!-- SpringBoot相关 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--mybatisplus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>${mybatisplus.version}</version>
        </dependency>
        <!--mysql 数据库相关-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.34</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
    </build>

</project>

2. 数据源配置类 (DataSourceConfig)

此类用于配置多个数据源,并将其分别标记为 PrimarySecondary,以便在需要时进行区分。

package org.songtang.springbootdynamic.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
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
public class DataSourceConfig {

    @Primary
    @Bean(name = "mainDateSource")
    @ConfigurationProperties(prefix = "spring.datasource.main")
    public DataSource mainDateSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "targetDateSource")
    @ConfigurationProperties(prefix = "spring.datasource.target")
    public DataSource targetDateSource(){
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean(name = "mainSessionFactory")
    public SqlSessionFactory mainSessionFactory(@Qualifier("mainDateSource")DataSource dataSource) throws Exception{
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
        mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/master/*.xml"));
        return mybatisSqlSessionFactoryBean.getObject();
    }

    @Bean(name = "targetSessionFactory")
    public SqlSessionFactory SessionFactory(@Qualifier("targetDateSource")DataSource dataSource) throws Exception{
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/slave/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "mainTransactionManager")
    public DataSourceTransactionManager mainTransactionManager(@Qualifier("mainDateSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "targetTransactionManager")
    public DataSourceTransactionManager targetTransactionManager(@Qualifier("targetDateSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

3. 数据源映射配置类

MasterMapperConfigSlaveMapperConfig 分别配置主数据源和从数据源的 Mapper

主数据源配置 (MasterMapperConfig)

package org.songtang.springbootdynamic.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan(basePackages = "org.songtang.springbootdynamic.mapper.master", sqlSessionFactoryRef = "mainSessionFactory")
public class MasterMapperConfig {
}

从数据源配置 (SlaveMapperConfig)

package org.songtang.springbootdynamic.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan(basePackages = "org.songtang.springbootdynamic.mapper.slave", sqlSessionFactoryRef = "targetSessionFactory")
public class SlaveMapperConfig {
}

4. 实体类 (Member)

Member 实体类用于表示数据库中的成员数据,并与 masterslave 两个数据源交互。

package org.songtang.springbootdynamic.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@TableName("member")
@Data
public class Member extends BaseEntity{
    private String name;
    private String phone;
    private Double amount;
}

5. Mapper 接口

Mapper 接口用于定义与数据库交互的方法。

主数据源 Mapper (MasterMapper)

package org.songtang.springbootdynamic.mapper.master;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.songtang.springbootdynamic.entity.Member;

@Mapper
public interface MasterMapper extends BaseMapper<Member> {
    // 主数据源相关操作
}

从数据源 Mapper (SlaveMapper)

package org.songtang.springbootdynamic.mapper.slave;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.songtang.springbootdynamic.entity.Member;

@Mapper
public interface SlaveMapper extends BaseMapper<Member> {
    // 从数据源相关操作
}

6. 控制器 (Controller)

控制器类用于定义对外暴露的 API 接口,用于操作不同数据源的数据。

package org.songtang.springbootdynamic.controller;

import org.songtang.springbootdynamic.entity.Member;
import org.songtang.springbootdynamic.service.YourService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class MultiDataSourceController {

    @Autowired
    private YourService yourService;

    // 使用主数据源插入数据
    @PostMapping("/master")
    public void addMasterEntity(@RequestBody Member masterEntity) {
        yourService.addMaster(masterEntity);
    }

    // 使用从数据源插入数据
    @PostMapping("/slave")
    public void addSlaveEntity(@RequestBody Member slaveEntity) {
        yourService.addSlave(slaveEntity);
    }
}

7. 使用示例

在项目中,可以通过调用控制器的 API 来测试不同数据源的功能:

  • 插入主数据源的数据: 通过 /api/master 接口插入数据
  • 插入从数据源的数据: 通过 /api/slave 接口插入数据

8. application.yml 配置 

application.yml 文件中需要配置主数据源和从数据源的连接信息:

spring:
  datasource:
    main:
      url: jdbc:mysql://localhost:3306/masterdb
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    target:
      url: jdbc:mysql://localhost:3306/slavedb
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

总结

通过以上配置,您可以在 Spring Boot 项目中成功实现多数据源的管理,分离不同的数据库操作。这样可以轻松处理不同数据源之间的事务以及数据交互,确保应用的高效性和可扩展性。

;