Part 1: 如何集成 (The "How-To")
在 Spring Boot 3.x 中集成 MyBatis 非常直接,主要得益于 MyBatis 官方提供的启动器 (Starter)。
第1步:添加依赖
这是最关键的一步。由于 Spring Boot 3.x 全面迁移到了 Jakarta EE 9+,你必须使用与之一致的 MyBatis Starter。
在你的 pom.xml 中,添加
mybatis-spring-boot-3-starter:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-3-starter</artifactId>
<version>3.0.3</version> <!-- 请使用最新的 3.x 版本 -->
</dependency>
<!-- 你还需要一个数据库驱动,例如 MySQL -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
注意:
- Spring Boot 2.x 使用的是 mybatis-spring-boot-starter。
- Spring Boot 3.x 必须 使用 mybatis-spring-boot-3-starter,因为它的底层依赖 mybatis-spring 已经适配了 jakarta.* 命名空间。
第2步:配置数据源和MyBatis
在 application.yml (或 .properties) 文件中,配置数据库连接信息和 MyBatis 的基本行为。
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database?useSSL=false
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
# 指定 Mapper XML 文件的位置
mapper-locations: classpath:mapper/*.xml
# 开启驼峰命名转换:将数据库的 a_column 映射到 Java 对象的 aColumn
configuration:
map-underscore-to-camel-case: true
第3步:创建 Mapper 接口
创建一个 Java 接口,并使用 @Mapper 注解标记它。Spring Boot 会扫描到这个注解,并为它创建实现类。
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import your.package.entity.User;
@Mapper // 关键注解
public interface UserMapper {
// 方式一:使用注解编写 SQL
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
// 方式二:方法名对应 XML 中的 id
User findByUsername(String username);
}
第4步:(可选) 创建 Mapper XML 文件
如果你有复杂的动态 SQL,推荐使用 XML。在 resources/mapper/ 目录下创建一个 UserMapper.xml 文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="your.package.mapper.UserMapper"> <!-- 命名空间必须是 Mapper 接口的全限定名 -->
<select id="findByUsername" resultType="your.package.entity.User">
SELECT * FROM user WHERE username = #{username}
</select>
</mapper>
第5步:注入并使用
现在你可以像注入任何其他 Spring Bean 一样,在你的服务层或控制层中直接注入并使用 UserMapper。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final UserMapper userMapper;
// 推荐使用构造器注入
@Autowired
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User getUserById(Long id) {
return userMapper.findById(id);
}
}
至此,集成工作就完成了。你不需要手动配置 SqlSessionFactory 或 SqlSessionTemplate,一切都已准备就绪。
Part 2: 集成机制 (The "Why it Works")
这部分是精髓,它解释了 Spring Boot 是如何通过“约定优于配置”和自动化配置来“接管”MyBatis 的。
其核心是 MybatisAutoConfiguration 类,它由
mybatis-spring-boot-3-starter 提供。
整个机制可以分解为以下几个关键步骤:
1. 触发自动化配置
当你将
mybatis-spring-boot-3-starter 添加到项目中时,Spring Boot 启动时会在 classpath 中找到它。这个 starter 包含了一个关键的入口点文件 (
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports),它告诉 Spring Boot 需要加载 MybatisAutoConfiguration。
MybatisAutoConfiguration 类本身被一系列 @ConditionalOn... 注解所标记,这意味着只有在满足特定条件时,这个自动化配置才会生效。最重要的条件是:
- @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }): 必须在 classpath 中能找到 MyBatis 的核心类。
- @ConditionalOnSingleCandidate(DataSource.class): Spring 容器中必须有且仅有一个 DataSource Bean。(这个 DataSource 是由 Spring Boot 的 DataSourceAutoConfiguration 自动根据你的 application.yml 配置创建的)。
2. 自动创建核心Bean
一旦条件满足,MybatisAutoConfiguration 就会开始工作,自动为你创建和配置 MyBatis 的核心组件 Bean:
- SqlSessionFactory: 这是 MyBatis 最核心的对象,负责创建 SqlSession。
- 自动化配置会创建一个 SqlSessionFactoryBean。
- 它会自动将第1步中找到的 DataSource 注入到 SqlSessionFactoryBean 中。
- 它会读取 application.yml 中 mybatis.mapper-locations 的配置,找到你所有的 Mapper XML 文件,并加载它们。
- 它还会读取 mybatis.configuration.* 下的配置(如 map-underscore-to-camel-case),并应用到 MyBatis 的 Configuration 对象中。
- 最终,SqlSessionFactoryBean 会创建出 SqlSessionFactory 这个 Bean,并放入 Spring 容器。
- SqlSessionTemplate: 这是一个线程安全的 SqlSession 实现,是 Spring 官方推荐的与 MyBatis 集成的方式。
- MybatisAutoConfiguration 会使用上面创建的 SqlSessionFactory 来构造一个 SqlSessionTemplate Bean。
- 它能自动管理 SqlSession 的生命周期,包括获取、使用、提交/回滚和关闭,并能无缝地融入 Spring 的事务管理。
3. 扫描并注册 Mapper 接口
这是最神奇的一步。你是如何能够直接 @Autowired 一个接口的?
- MybatisAutoConfiguration 内部通过 @Import(AutoConfiguredMapperScannerRegistrar.class) 引入了一个特殊的配置类。
- 这个类会触发一个 Mapper 扫描过程。它会扫描你的主应用程序类(@SpringBootApplication 所在的类)所在的包及其子包,寻找所有被 @Mapper 注解标记的接口。
- 对于每一个找到的 Mapper 接口(如 UserMapper),它会使用一个名为 MapperFactoryBean 的工厂 Bean 在 Spring 容器中注册一个代理对象。
这个代理对象就是你最终注入并使用的东西。当你调用 userMapper.findById(1L) 方法时:
- 你实际上是在调用这个动态生成的代理对象的方法。
- 代理对象内部持有对 SqlSessionTemplate 的引用。
- 它根据方法名(或注解信息)找到对应的 SQL 语句(来自注解或 XML)。
- 它使用 SqlSessionTemplate 来执行这条 SQL,并将参数传递过去。
- SqlSessionTemplate 负责处理底层的 JDBC 调用和事务。
- 最后,代理对象将查询结果返回给你。
总结机制
(一个简化的流程图示意)
- Starter 触发:mybatis-spring-boot-3-starter 引入依赖,并让 Spring Boot 加载 MybatisAutoConfiguration。
- 条件检查:MybatisAutoConfiguration 检查 DataSource 是否存在,存在则激活。
- 核心Bean创建:自动配置 SqlSessionFactory (绑定数据源和XML) 和 SqlSessionTemplate (线程安全的执行器)。
- Mapper 扫描与代理:自动扫描 @Mapper 接口,并为每个接口创建一个动态代理 Bean,该 Bean 封装了所有数据库操作的细节。
- 依赖注入:开发者可以直接 @Autowired 这些代理后的 Mapper Bean,像调用一个普通 Java 方法一样执行数据库操作,完全屏蔽了底层的复杂性。
总而言之,Spring Boot 3.x 与 MyBatis 的集成机制是一个典型的**“自动化配置”+“动态代理”**的范例。它将所有繁琐的、模板化的配置工作全部自动化,让开发者只需关注业务逻辑(SQL语句)和接口定义,实现了真正意义上的“开箱即用”。