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

相关推荐
勇哥java实战分享2 小时前
10GB vs 600MB:我们弃用 GitLab,选择了这个轻量级神器
后端
编程修仙2 小时前
第九篇 异常统一处理
spring boot
HashTang2 小时前
【AI 编程实战】第 3 篇:后端小白也能写 API:AI 带我 1 小时搭完 Next.js 服务
前端·后端·ai编程
学到头秃的suhian2 小时前
Springboot进阶知识
java·spring boot·spring
白宇横流学长2 小时前
基于SpringBoot实现的电子发票管理系统
java·spring boot·后端
白宇横流学长2 小时前
基于SpringBoot实现的智慧就业管理系统
java·spring boot·后端
用户25542581802163 小时前
Spring AI(二):如何在使用的时候指定角色,使用模板
后端
YDS8293 小时前
SpringCloud —— 黑马商城的项目拆分和Nacos
spring boot·后端·spring cloud
卜锦元3 小时前
Golang中make()和new()的区别与作用?
开发语言·后端·golang