MyBatis-Flex多数据源:在SpringBoot3中使用MyBatis-Flex实现多数据源

一、场景需求与方案选型

1.1 什么是多数据源

本文中的多数据源指:单个SpringBoot服务 同时连接并使用 多个不同的数据库

1.2 为什么选择 MyBatis-Flex

相较于传统方案需要自行配置 DataSource、TransactionManager 等组件,MyBatis-Flex 通过注解驱动实现了:

  • 零配置多数据源:仅需简单配置即可管理多个数据源
  • 声明式切换:通过 @Table 注解即可指定实体类对应的数据源
  • 事务无缝集成:天然支持 Spring 事务管理

相较于 Spring Boot 原生的多数据源配置,MyBatis-Flex 的方案更简洁高效。

二、官方文档

官方文档:MyBatis-Flex 多数据源

2.1 多数据源配置(yml)

2.2 指定数据源(数据源切换配置)

三、环境与项目准备

3.1 技术栈与版本

  • SpringBoot: 3.4.5
  • MyBatis-Flex: 1.10.9
  • 数据库: MySQL 8.0
  • 驱动: mysql-connector-j

3.2 项目创建

3.3 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 https://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.4.5</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>hello-mybatis-flex-multiple-datasource</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-mybatis-flex-multiple-datasource</name>
    <description>MyBatis-Flex 多数据源</description>

    <properties>
        <java.version>21</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.mybatis-flex</groupId>
            <artifactId>mybatis-flex-spring-boot3-starter</artifactId>
            <version>1.10.9</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.24</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>
    </build>

</project>

3.4 数据库准备

创建数据库和表,插入测试数据:

1. 用户数据库(user_db
CREATE DATABASE `user_db` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */
2. 用户表(user_db.user
-- user_db.`user` definition

CREATE TABLE `user` (
  `user_id` bigint NOT NULL COMMENT '用户ID',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(100) NOT NULL COMMENT '密码',
  `balance` decimal(10,2) DEFAULT '0.00' COMMENT '账户余额',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
3. 订单数据库(order_db
CREATE DATABASE `order_db` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */
4. 订单表( order_db.order
-- order_db.`order` definition

CREATE TABLE `order` (
  `order_id` bigint NOT NULL COMMENT '订单ID',
  `user_id` bigint NOT NULL COMMENT '下单用户ID',
  `order_amount` decimal(10,2) NOT NULL COMMENT '订单金额',
  `order_status` tinyint DEFAULT '0' COMMENT '0-待支付,1-已支付,2-已取消',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间',
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
5. 插入测试数据
插入 user_db.user 表的测试数据
-- 插入 user_db.user 表的测试数据示例:
-- 用户测试数据(合理覆盖默认值、唯一性约束和数据类型)
INSERT INTO `user` (`user_id`, `username`, `password`, `balance`, `create_time`) VALUES
(1005, '张伟', 'e10adc3949ba59abbe56e057f20f883e', 4500.00, '2024-01-15 09:10:00'),  -- 密码:123456
(1006, '王芳', 'd8578edf8458ce06fbc5bb76a58c5ca4', 0.00, CURRENT_TIMESTAMP),      -- 密码:qwerty(余额默认值)
(1007, '李娜', '5f4dcc3b5aa765d61d8327deb882cf99', 1234.56, '2024-01-17 16:45:00'), -- 密码:password
(1008, '陈勇', '25f9e794323b453885f5181f1b624d0b', 78900.33, '2024-01-18 20:00:00'); -- 密码:123456789
插入 order_db.order 表的测试数据
-- 插入 order_db.order 表的测试数据示例:
-- 订单测试数据(覆盖状态、金额范围、时间类型)
INSERT INTO `order` (`order_id`, `user_id`, `order_amount`, `order_status`, `create_time`) VALUES
(2001, 1001, 150.00, 1, '2024-01-20 10:00:00'),          -- 用户 1001 的已支付订单
(2002, 1005, 99.99,  0, CURRENT_TIMESTAMP),             -- 用户 1005 的待支付订单(使用默认时间)
(2003, 1003, 450.50, 2, '2024-01-19 15:30:00'),        -- 用户 1003 的已取消订单
(2004, 1008, 2000.00, 1, '2024-01-18 14:00:00'),       -- 用户 1008 的大额已支付订单
(2005, 1002, 300.00,  0, CURRENT_TIMESTAMP);            -- 用户 1002 的待支付订单

四、MyBatis-Flex 多数据源配置与使用

步骤 1: 配置多数据源 (application.yml)

spring:
  application:
    name: hello-mybatis-flex-multiple-datasource

mybatis-flex:
  datasource:
    user_db:
      url: jdbc:mysql://127.0.0.1:3306/user_db
      username: flex_test_user
      password: 12345678
    order_db:
      url: jdbc:mysql://127.0.0.1:3306/order_db
      username: flex_test_user
      password: 12345678

关键点说明

  • mybatis-flex.datasource 下直接配置多个数据源
  • 每个数据源定义一个唯一名称 (如 user_db, order_db)
  • 配置项与传统 spring.datasource 相同 (url, username, password)

步骤 2: 实体类绑定数据源

通过 @Table(dataSource = "数据源名称") 注解指定实体类对应的数据源。

用户实体(绑定到 user_db
package com.example.hello.mybatisflex.multiple.datasource.db.user.entity;

import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 用户表实体类
 */
@Data
@Table(value = "user", dataSource = "user_db")
public class User {
    /**
     * 用户ID(主键)
     */
    @Id(keyType = KeyType.Auto)
    private Long userId;

    /**
     * 用户名(唯一约束)
     */
    private String username;

    /**
     * 密码(加密存储)
     */
    private String password;

    /**
     * 账户余额(单位:元,精度保留两位小数)
     */
    private BigDecimal balance;

    /**
     * 创建时间(默认当前时间)
     */
    private LocalDateTime createTime;
}
订单实体(绑定到 order_db
package com.example.hello.mybatisflex.multiple.datasource.db.order.entity;

import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 订单表实体类
 */
@Data
@Table(value = "order", dataSource = "order_db")
public class Order {
    /**
     * 订单ID(主键)
     */
    @Id(keyType = KeyType.Auto)
    private Long orderId;

    /**
     * 用户ID(关联 user.user_id)
     */
    private Long userId;

    /**
     * 订单金额(单位:元,非空,精度保留两位小数)
     */
    private BigDecimal orderAmount;

    /**
     * 订单状态(0-待支付,1-已支付,2-已取消)
     */
    private Integer orderStatus;

    /**
     * 下单时间(默认当前时间)
     */
    private LocalDateTime createTime;
}

步骤 3: 创建 Mapper 接口

Mapper 接口无需特殊处理,继承 BaseMapper 即可。

UserMapper.java:

package com.example.hello.mybatisflex.multiple.datasource.db.user.mapper;

import com.example.hello.mybatisflex.multiple.datasource.db.user.entity.User;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

OrderMapper.java:

package com.example.hello.mybatisflex.multiple.datasource.db.order.mapper;

import com.example.hello.mybatisflex.multiple.datasource.db.order.entity.Order;
import com.mybatisflex.core.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}

五、功能测试与验证

5.1 单元测试类

package com.example.hello.mybatisflex.multiple.datasource;

import com.example.hello.mybatisflex.multiple.datasource.db.order.entity.Order;
import com.example.hello.mybatisflex.multiple.datasource.db.order.mapper.OrderMapper;
import com.example.hello.mybatisflex.multiple.datasource.db.user.entity.User;
import com.example.hello.mybatisflex.multiple.datasource.db.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@Slf4j
@SpringBootTest
class MultipleDatasourceTest {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Test
    void testUserMapper() {
        List<User> users = userMapper.selectAll();
        log.info("users: {}", users);
    }

    @Test
    void testOrderMapper() {
        List<Order> orders = orderMapper.selectAll();
        log.info("orders: {}", orders);
    }

    @Test
    void testMultipleDatasource() {
        List<User> users = userMapper.selectAll();
        log.info("用户列表:{}", users);

        List<Order> orders = orderMapper.selectAll();
        log.info("订单列表:{}", orders);

        User user = userMapper.selectOneById(1005L);
        log.info("测试重新切换到用户数据库,单个用户:{}", user);
    }

}

5.2 测试结果及分析

执行 testMultipleDatasource() 的日志输出

17:03:24.141 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.example.hello.mybatisflex.multiple.datasource.MultipleDatasourceTest]: MultipleDatasourceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
17:03:24.509 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.example.hello.mybatisflex.multiple.datasource.HelloMybatisFlexMultipleDatasourceApplication for test class com.example.hello.mybatisflex.multiple.datasource.MultipleDatasourceTest

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.4.5)

2025-05-24T17:03:25.990+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] c.e.h.m.m.d.MultipleDatasourceTest       : Starting MultipleDatasourceTest using Java 21.0.1 with PID 5236 (started by SongGuanxun in E:\hello-world\hello-mybatis-flex-multiple-datasource)
2025-05-24T17:03:25.995+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] c.e.h.m.m.d.MultipleDatasourceTest       : No active profile set, falling back to 1 default profile: "default"
  __  __       _           _   _       _____ _           
 |  \/  |_   _| |__   __ _| |_(_)___  |  ___| | _____  __
 | |\/| | | | | '_ \ / _` | __| / __| | |_  | |/ _ \ \/ /
 | |  | | |_| | |_) | (_| | |_| \__ \ |  _| | |  __/>  < 
 |_|  |_|\__, |_.__/ \__,_|\__|_|___/ |_|   |_|\___/_/\_\
         |___/ v1.10.9 https://mybatis-flex.com
2025-05-24T17:03:29.336+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] c.e.h.m.m.d.MultipleDatasourceTest       : Started MultipleDatasourceTest in 4.35 seconds (process running for 7.449)
Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build what is described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0.3
WARNING: A Java agent has been loaded dynamically (D:\maven\repository\net\bytebuddy\byte-buddy-agent\1.15.11\byte-buddy-agent-1.15.11.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release
Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2025-05-24T17:03:32.283+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2025-05-24T17:03:33.805+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] c.e.h.m.m.d.MultipleDatasourceTest       : 用户列表:[User(userId=1005, username=张伟, password=e10adc3949ba59abbe56e057f20f883e, balance=4500.00, createTime=2024-01-15T09:10), User(userId=1006, username=王芳, password=d8578edf8458ce06fbc5bb76a58c5ca4, balance=0.00, createTime=2025-05-15T22:54:18), User(userId=1007, username=李娜, password=5f4dcc3b5aa765d61d8327deb882cf99, balance=1234.56, createTime=2024-01-17T16:45), User(userId=1008, username=陈勇, password=25f9e794323b453885f5181f1b624d0b, balance=78900.33, createTime=2024-01-18T20:00)]
2025-05-24T17:03:33.820+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2} inited
2025-05-24T17:03:33.883+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] c.e.h.m.m.d.MultipleDatasourceTest       : 订单列表:[Order(orderId=2001, userId=1001, orderAmount=150.00, orderStatus=1, createTime=2024-01-20T10:00), Order(orderId=2002, userId=1005, orderAmount=99.99, orderStatus=0, createTime=2025-05-15T23:02:48), Order(orderId=2003, userId=1003, orderAmount=450.50, orderStatus=2, createTime=2024-01-19T15:30), Order(orderId=2004, userId=1008, orderAmount=2000.00, orderStatus=1, createTime=2024-01-18T14:00), Order(orderId=2005, userId=1002, orderAmount=300.00, orderStatus=0, createTime=2025-05-15T23:02:48)]
2025-05-24T17:03:33.895+08:00  INFO 5236 --- [hello-mybatis-flex-multiple-datasource] [           main] c.e.h.m.m.d.MultipleDatasourceTest       : 测试重新切换到用户数据库,单个用户:User(userId=1005, username=张伟, password=e10adc3949ba59abbe56e057f20f883e, balance=4500.00, createTime=2024-01-15T09:10)

进程已结束,退出代码为 0

测试结论成功验证
  1. 成功同时连接并操作 user_dborder_db 两个数据库
  2. 在同一个方法内,根据 @Table 注解自动切换数据源
  3. 数据源切换操作对开发者透明,无需手动干预
  4. 跨数据源事务需额外处理(本示例未涉及)

六、重要注意事项

1. 数据源命名

  • yml 中配置的数据源名称 (user_db, order_db) 必须与实体类 @Table 注解中 dataSource 属性的值严格一致
  • 名称建议使用有意义的英文,避免特殊字符。

2. 事务管理

七、Spring Boot 原生数据源配置失效

在 SpringBoot 项目中使用 MyBatis-Flex 配置多数据源时,原生 spring.datasource 配置失效,且未显式指定数据源的 SQL 操作会默认使用 MyBatis-Flex 配置的第一个数据源。

深度解析
详细了解此行为背后的机制,请参考:《MyBatis-Flex 多数据源配置行为解析:为什么 SpringBoot 默认数据源会失效?(原生 spring.datasource 配置失效)》

八、总结

通过 MyBatis-Flex 实现 Spring Boot 多数据源开发非常简洁高效:

  1. 配置简单:在 yml 中直接定义多个数据源
  2. 使用直观:通过 @Table(dataSource="...") 注解绑定实体与数据源
  3. 自动切换:框架根据实体注解自动路由到正确数据源
  4. 无侵入性:Mapper 接口和 Service 层代码无需关注数据源切换细节

这种方案显著降低了多数据源使用的复杂度,是 Spring Boot 项目中处理多数据库需求的推荐方式。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐