MyBatis基础入门《十》Spring Boot 整合 MyBatis:从单数据源到多数据源实战

一、快速集成:单数据源配置

1. 添加 Maven 依赖

复制代码
<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MyBatis Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.3</version> <!-- 注意:适配 Spring Boot 3.x -->
    </dependency>

    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

🔔 注意:

  • Spring Boot 3.x 需使用 mybatis-spring-boot-starter 3.x+
  • 若用 Spring Boot 2.x,请降级到 2.3.x。

2. 配置 application.yml

复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml     # XML 文件位置
  type-aliases-package: com.charles.entity     # 实体类别名包
  configuration:
    map-underscore-to-camel-case: true         # 下划线转驼峰
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 控制台打印 SQL

3. 编写实体类 & Mapper

复制代码
// User.java
package com.charles.entity;
public class User {
    private Integer id;
    private String username;
    // getter / setter
}

// UserMapper.java
package com.charles.mapper;

import com.charles.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Mapper // 👈 关键注解!
public interface UserMapper {
    User selectById(Integer id);
    void insert(User user);
}

✅ 两种注册 Mapper 方式(二选一):

  1. 在每个 Mapper 接口上加 @Mapper
  2. 在启动类上加 @MapperScan("com.charles.mapper")(推荐,避免重复注解)。

4. Service 层 + 事务控制

复制代码
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    // ✅ 自动开启事务(默认 REQUIRED)
    @Transactional
    public void createUser(User user) {
        userMapper.insert(user);
        
        // 模拟异常:若此处出错,insert 会回滚
        if (user.getUsername().contains("error")) {
            throw new RuntimeException("模拟异常");
        }
    }

    public User getUser(Integer id) {
        return userMapper.selectById(id); // 只读,无需事务
    }
}

💡 Spring 的 @Transactional 与 MyBatis 完美协作,无需手动 commit/rollback!


二、进阶:配置多数据源(Multi-DataSource)

场景说明

  • 主库(master):写操作(订单、用户注册)
  • 从库(slave):读操作(报表、查询)

步骤 1:添加两个数据源配置

复制代码
spring:
  datasource:
    master:
      jdbc-url: jdbc:mysql://localhost:3306/master_db
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave:
      jdbc-url: jdbc:mysql://localhost:3306/slave_db
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver

⚠️ 注意:Spring Boot 2.7+ 使用 jdbc-url 而非 url(HikariCP 要求)。


步骤 2:创建主从数据源配置类

复制代码
// MasterDataSourceConfig.java
@Configuration
@MapperScan(
    basePackages = "com.charles.mapper.master",
    sqlSessionFactoryRef = "masterSqlSessionFactory"
)
public class MasterDataSourceConfig {

    @Bean
    @Primary // 主数据源
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource ds) 
        throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryFactoryBean();
        factory.setDataSource(ds);
        factory.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath:mapper/master/*.xml"));
        return factory.getObject();
    }

    @Bean
    @Primary
    public SqlSessionTemplate masterSqlSessionTemplate(
        @Qualifier("masterSqlSessionFactory") SqlSessionFactory sf) {
        return new SqlSessionTemplate(sf);
    }
}

// SlaveDataSourceConfig.java(类似,去掉 @Primary,包路径改为 slave)

步骤 3:按用途划分 Mapper 包

复制代码
src/main/java
└── com.charles.mapper
    ├── master
    │   └── UserWriteMapper.java   // 写操作
    └── slave
        └── UserReadMapper.java    // 读操作

✅ 这样,写操作走主库,读操作走从库,实现读写分离!


三、常见问题 & 最佳实践

❓ Q1:启动报错 "No qualifying bean of type 'XXXMapper'"?

  • 原因:未正确扫描 Mapper 接口;
  • 解决:检查 @MapperScan 包路径是否包含 Mapper 所在包。

❓ Q2:事务不生效?

  • 原因1:方法非 public;
  • 原因2:自调用(this.method());
  • 原因3:异常被捕获未抛出;
  • ✅ 解决:确保 @Transactional 方法被外部调用,且抛出 RuntimeException。

✅ 最佳实践

  • 使用 @MapperScan 统一管理,避免每个接口加 @Mapper
  • 多数据源时,严格分离读写 Mapper 包;
  • 生产环境关闭 log-impl,改用日志框架(如 Logback)记录 SQL;
  • 结合 DruidHikariCP 监控连接池状态。

四、扩展:整合 PageHelper 分页插件

复制代码
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.7</version>
</dependency>

使用:

复制代码
public List<User> getUsers(int pageNum, int pageSize) {
    PageHelper.startPage(pageNum, pageSize);
    return userMapper.selectAll(); // 自动分页
}

🌟 无需修改 SQL,一行代码实现物理分页!


五、总结

能力 Spring Boot + MyBatis 实现方式
单数据源 mybatis-spring-boot-starter + application.yml
事务管理 @Transactional(由 Spring 管理)
多数据源 多个 DataSource + @MapperScan 分包
分页 PageHelper Starter
SQL 日志 mybatis.configuration.log-impl

核心优势
"零 XML 配置、自动事务、无缝整合、生产就绪!"

相关推荐
摇滚侠9 分钟前
《SpringBoot 3:入门与应用实战》第 13 章 整合 MyBatis 使用 MyBatis-Plus 阅读笔记 40
spring boot·笔记·mybatis
jyOverQ3 小时前
RabbitMQ 消息积压怎么办?Prefetch、消费者并发与扩容
分布式·后端·rabbitmq
东风破_10 小时前
从跨域到 WebSocket:前端跨域方案、SSE 与双向实时通信详解
前端·后端
行百里er12 小时前
Gateway 上别硬塞 MVC:DeferredImportSelector 看菜下锅
spring boot·后端·开源
名字还没想好☜12 小时前
Java 遍历时删元素抛 ConcurrentModificationException:fail-fast 原理与三种正确删法
后端
IT_陈寒13 小时前
React Hooks闭包陷阱差点让我加班到凌晨
前端·人工智能·后端
黑马程序员毕设13 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
码事漫谈13 小时前
本体论,彻底懂
后端
创新技术阁13 小时前
FastapiAdmin 系统日志体系与核心配置参数详解
前端·后端·fastapi
掘金者阿豪13 小时前
SQL Server 迁到金仓,真正麻烦的不是数据,而是这些 T-SQL
后端