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 配置、自动事务、无缝整合、生产就绪!"

相关推荐
BlockChain8881 天前
Spring框架终极入门指南(12000字深度解析)
java·后端·python·spring
学嵌入式的小杨同学1 天前
【嵌入式 C 语言实战】栈、队列、二叉树核心解析:存储原理 + 应用场景 + 实现思路
linux·c语言·网络·数据结构·数据库·后端·spring
❀͜͡傀儡师1 天前
SpringBoot与Artemis整合,实现航空行李追踪消息中枢系统
java·spring boot·后端
qq_256247051 天前
AG-UI:让 AI 走出聊天框的“界面革命”
后端
麦兜*1 天前
SpringBoot Actuator监控端点详解,打造生产级应用健康检查
java·spring boot·后端
无限进步_1 天前
二叉搜索树(BST)详解:从原理到实现
开发语言·数据结构·c++·ide·后端·github·visual studio
悟能不能悟1 天前
Spring Boot 中处理跨域资源
java·spring boot·后端
qq_12498707531 天前
基于springboot+vue的无人机共享管理系统(源码+论文+部署+安装)
java·vue.js·spring boot·后端·毕业设计·无人机·计算机毕业设计
源码获取_wx:Fegn08951 天前
计算机毕业设计|基于springboot + vue网上超市系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring·课程设计
Coder_Boy_1 天前
基于SpringAI的在线考试系统-知识点管理与试题管理模块联合回归测试文档
前端·人工智能·spring boot·架构·领域驱动