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

相关推荐
㳺三才人子3 分钟前
初探 Spring Framework OncePerRequestFilter
spring boot·spring·junit
这是程序猿15 分钟前
基于java的ssm框架学生作业管理系统
java·开发语言·spring boot·spring·学生作业管理系统
千百元17 分钟前
限制网段访问服务器端口63790
java·网络·mybatis
努力的小雨33 分钟前
从“Agent 元年”到 AI IDE 元年——2025 我与 Vibe Coding 的那些事儿
后端·程序员
Caarlossss1 小时前
mybatis
java·数据库·tomcat·maven·mybatis·mybatis-spring
源码获取_wx:Fegn08951 小时前
基于springboot + vue小区人脸识别门禁系统
java·开发语言·vue.js·spring boot·后端·spring
wuxuanok1 小时前
Go——Swagger API文档访问500
开发语言·后端·golang
liuc03172 小时前
AI下调用redis并调用deepseek
数据库·redis·mybatis
用户21411832636022 小时前
白嫖Google Antigravity!Claude Opus 4.5免费用,告别token焦虑
后端
爬山算法2 小时前
Hibernate(15)Hibernate中如何定义一个实体的主键?
java·后端·hibernate