Java 持久层框架 MyBatis 全面详解(附带Idea添加对应的XML文件模板教程)
一、介绍
MyBatis 是一款持久层框架,原名为 iBatis,2010 年由 Apache 迁移到 Google Code 并更名,2013 年又迁移到 GitHub。它消除了几乎所有的 JDBC 代码、手动设置参数和获取结果集的操作,通过XML 或注解的方式将 SQL 与 Java 代码解耦,支持自定义 SQL、存储过程和高级映射,是 Java 生态中主流的 ORM(对象关系映射)框架之一。
特点:
- 轻量级 & 灵活:相比 Hibernate 等全自动化 ORM 框架,MyBatis 不强制封装所有 SQL,允许开发者手写 SQL,适配复杂业务场景(如多表联查、复杂条件筛选)。
- SQL 与代码解耦:SQL 可集中管理在 XML 文件中,便于维护和优化(DBA 可直接修改 SQL 无需改动代码)。
- 强大的映射能力:支持一对一、一对多、多对多等复杂关系映射,无需手动封装结果集。
- 减少 JDBC 冗余代码:自动处理连接获取、参数设置、结果集解析、连接关闭等操作,避免手动管理导致的错误。
- 动态 SQL:提供
<if>、<where>、<foreach>等标签,可根据条件动态拼接 SQL,解决拼接 SQL 时的空格、逗号等问题。
补充:
什么是ORM?
对象关系映射(ORM,Object-Relational Mapping)是一种编程技术,它的核心是把 "数据库中的表 / 记录" 和 "编程语言中的对象 / 实例" 做对应,让开发者可以用 "操作对象" 的方式来操作数据库,无需直接写 SQL(或减少 SQL 的编写)。
简单说:
数据库里的表 → 对应编程语言里的类;
表中的一行记录 → 对应类的一个对象实例;
表中的字段 → 对应类的属性;
对数据库的增删改查 → 对应对对象的创建、修改、删除、查询。
MyBatis 执行流程:
每次数据库操作执行
项目启动时,仅执行一次
解析配置生成 Configuration 全局配置对象
动态生成代理类
接收业务层调用
配置文件/注解
(mybatis-config.xml/Mapper.xml/注解)
SqlSessionFactoryBuilder
SqlSessionFactory
(全局唯一)
SqlSession
(单次会话,非线程安全)
Executor
(执行器,处理缓存/事务)
StatementHandler
(语句处理器,构建SQL)
ParameterHandler
(参数处理器,设置SQL参数)
JDBC操作
(PreparedStatement执行SQL)
ResultSetHandler
(结果集处理器,映射结果)
结果返回
(封装为实体类/Map等)
Mapper接口(代理类)
二、核心组件
1. SqlSessionFactory
- 作用:创建
SqlSession的工厂类,是 MyBatis 的核心入口,全局唯一(通常通过单例模式创建)。 - 创建方式:通过
SqlSessionFactoryBuilder解析 MyBatis 核心配置文件(mybatis-config.xml)或自定义配置类生成。
2. SqlSession
- 作用:代表与数据库的一次会话,是执行 SQL 的核心对象,提供了增删改查的方法(如
selectOne、insert、update等)。 - 生命周期:单次请求 / 方法级别,用完需及时关闭(否则会导致连接泄漏)。
- 注意:
SqlSession不是线程安全的,不能在多线程中共享。
3. Mapper 接口(映射器)
-
作用:MyBatis 采用 "接口 + XML / 注解" 的方式定义 SQL,Mapper 接口是 SQL 操作的抽象层,无需实现类(MyBatis 动态生成代理类)。
-
示例:
javapublic interfadce UserMapper { // 通过注解定义SQL @Select("SELECT * FROM user WHERE id = #{id}") User selectUserById(Long id); // 通过XML定义SQL(推荐复杂SQL) List<User> selectUserByCondition(UserCondition condition); }
4. 核心配置文件(mybatis-config.xml)
MyBatis 的全局配置文件,包含环境(数据源、事务)、类型别名、插件、映射器等核心配置:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 环境配置:数据源、事务管理器 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!-- 事务管理:JDBC/MANAGED -->
<dataSource type="POOLED"> <!-- 数据源:POOLED/UNPOOLED/JNDI -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 映射器:指定Mapper接口或XML文件位置 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<!-- 或通过接口包扫描 -->
<!-- <package name="com.example.mapper"/> -->
</mappers>
</configuration>
5. Mapper XML 文件
存放 SQL 语句和结果映射规则,核心标签包括:
<select>:查询语句
<insert>:插入语句
<update>:更新语句
<delete>:删除语句
<resultMap>:自定义结果集映射(解决字段名与实体属性名不一致、关联查询等)
示例(UserMapper.xml):
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace对应Mapper接口全类名 -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 自定义结果映射:解决字段名(如user_name)与属性名(userName)不一致 -->
<resultMap id="UserResultMap" type="com.example.entity.User">
<id column="id" property="id"/> <!-- 主键映射 -->
<result column="user_name" property="userName"/>
<result column="age" property="age"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- 查询:引用自定义resultMap,参数通过#{参数名}接收 -->
<select id="selectUserById" resultMap="UserResultMap">
SELECT id, user_name, age, create_time FROM user WHERE id = #{id}
</select>
<!-- 动态SQL:根据条件拼接查询条件 -->
<select id="selectUserByCondition" resultMap="UserResultMap">
SELECT id, user_name, age, create_time FROM user
<where>
<if test="userName != null and userName != ''">
AND user_name LIKE CONCAT('%', #{userName}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
<!-- 插入:返回自增主键 -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (user_name, age, create_time)
VALUES (#{userName}, #{age}, #{createTime})
</insert>
</mapper>
三、核心特性
1. 参数传递
MyBatis 支持多种参数传递方式:
单个参数:直接通过 #{参数名} 接收(参数名可任意,推荐与接口参数名一致)。
多个参数:
方式 1:使用@Param注解命名参数:
java
User selectUserByUserNameAndAge(@Param("userName") String userName, @Param("age") Integer age)
方式 2:封装为实体类 / Map 传递。
数组 / 集合参数:结合<foreach>标签遍历,如批量删除:
xml
<delete id="batchDeleteUser">
DELETE FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
2. 动态 SQL
MyBatis 提供丰富的动态 SQL 标签,解决手动拼接 SQL 的痛点:
| 标签 | 作用 |
|---|---|
<if> |
条件判断 |
<where> |
自动处理 AND/OR 前缀 |
<set> |
自动处理更新语句的逗号 |
<foreach> |
遍历集合(如 IN 条件) |
<choose> |
类似 Java 的 switch 语句 |
<trim> |
自定义字符串截取 |
3. 结果映射
默认映射:字段名与实体属性名完全一致时,无需自定义 resultMap。
自定义映射:通过resultMap解决:
字段名与属性名不一致(如数据库 user_name → 实体 userName);
关联查询(一对一 <association>、一对多 <collection>)。
示例(一对多映射):
xml
<resultMap id="OrderResultMap" type="com.example.entity.Order">
<id column="order_id" property="orderId"/>
<result column="order_no" property="orderNo"/>
<!-- 一对多:订单关联多个订单项 -->
<collection property="orderItems" ofType="com.example.entity.OrderItem">
<id column="item_id" property="itemId"/>
<result column="product_name" property="productName"/>
</collection>
</resultMap>
补:如何去开启全局驼峰命名映射(数据库:user_id → 实体类:userId):
方式 A:在mybatis-config.xml中配置:
xml
<settings>
<!-- 开启下划线→驼峰自动映射(user_id → userId) -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
方式 B:Spring Boot 项目在application.yml中配置:
yaml
mybatis:
configuration:
map-underscore-to-camel-case: true
4. 缓存机制
MyBatis 缓存(一级 / 二级)的核心目的是提升系统性能、降低数据库压力,本质是 "用内存换速度"------ 把高频访问的数据库查询结果暂存到内存中,后续相同查询直接从内存取数据,无需重复访问数据库。
简单举个例子:
你可以把数据库比作咖啡店的「后厨」,查询请求比作顾客点咖啡,缓存比作吧台的「保温柜」:
没有缓存:
每个顾客点同款拿铁,后厨都要重新磨豆、萃取、冲调(每次查询都走数据库),慢且费资源;
有缓存:
后厨冲好一大壶拿铁放进保温柜,后续点拿铁的顾客直接从保温柜取(查缓存),速度快、后厨压力小。
MyBatis 一级缓存 = 「单个服务员的专属保温柜」(只服务自己接待的顾客);
MyBatis 二级缓存 = 「全店共享的保温柜」(所有服务员都能用来给顾客取咖啡)。
MyBatis 提供两级缓存,默认开启一级缓存,关闭二级缓存:
一级缓存 :基于 SqlSession 的本地缓存,同一 SqlSession 中相同 SQL 查询会复用结果(单次会话内重复查询),关闭 SqlSession 后缓存失效。
二级缓存 :基于 Mapper 命名空间的全局缓存,多个 SqlSession 可共享(多会话共享静态数据),需手动开启(在 Mapper XML 中添加 <cache/>),且实体类需实现 Serializable。
四、MyBatis 与 Spring/Spring Boot 集成
实际开发中,MyBatis 通常与 Spring/Spring Boot 集成,核心依赖:
xml
<!-- Spring Boot 整合 MyBatis 起步依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
依赖版本适配表
| Spring Boot 版本 | MyBatis-Spring-Boot-Starter 版本 | MyBatis 核心版本 | Spring 版本 | 适配说明 |
|---|---|---|---|---|
| 2.0.x | 2.0.x | 3.5.0+ | 5.0.x | Spring Boot 2.0 基线版本 |
| 2.1.x | 2.1.x | 3.5.3+ | 5.1.x | 兼容 Java 8+ |
| 2.2.x | 2.2.x | 3.5.5+ | 5.2.x | 优化连接池适配 |
| 2.3.x | 2.3.x | 3.5.7+ | 5.3.x | 主流稳定版本,推荐中小项目 |
| 2.4.x - 2.7.x | 2.4.x - 2.3.x(2.3.x 兼容) | 3.5.9+ | 5.3.x - 5.3.20+ | Spring Boot 2.x 最终稳定版 |
| 3.0.x - 3.1.x | 3.0.x - 3.1.x | 3.5.10+ | 6.0.x - 6.1.x | 适配 Spring 6、Java 17+ |
| 3.2.x+ | 3.2.x+ | 3.5.13+ | 6.1.x+ | 最新版本,适配 Spring 6.1+ |
Spring Boot 配置(application.yml)
yaml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml # Mapper XML 文件位置
type-aliases-package: com.example.entity # 实体类别名包
configuration:
map-underscore-to-camel-case: true # 自动将下划线命名转换为驼峰命名(如user_name → userName)
cache-enabled: false # 关闭二级缓存
常用注解
@Mapper:标注在 Mapper 接口上,让 Spring 扫描并创建代理对象。
@MapperScan:在启动类上扫描 Mapper 接口包(替代每个接口加@Mapper):
java
@SpringBootApplication
@MapperScan("com.example.mapper") // 扫描Mapper接口包
public class MyBatisApplication {
public static void main(String[] args) {
SpringApplication.run(MyBatisApplication.class, args);
}
}
五、适用场景
- 适合需要自定义 SQL、对性能要求高的场景(如电商、金融);
- 适合数据库结构复杂、需要灵活调整 SQL 的项目;
- 不适合完全追求 "零 SQL" 的快速开发场景(可选择 JPA/Hibernate)。
六、总结
MyBatis 以 "半自动化 ORM" 为核心,平衡了 SQL 灵活性和开发效率,既保留了开发者对 SQL 的控制权,又简化了 JDBC 操作。它是 Java 后端开发中最常用的持久层框架之一,尤其在互联网项目中广泛应用,掌握其核心组件、动态 SQL、结果映射是使用 MyBatis 的关键。
七、补充
idea使用mybatis-xml自定义模板创建文件
打开File -- Setting

打开Editor -- File and Code Templates --- 中间的"+"号

mybatis-xml文件模板如下:
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="">
</mapper>
配置mybatis-config.xml步骤一致:
模板:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 环境配置:数据源、事务管理器 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!-- 事务管理:JDBC/MANAGED -->
<dataSource type="POOLED"> <!-- 数据源:POOLED/UNPOOLED/JNDI -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 映射器:指定Mapper接口或XML文件位置 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
<!-- 或通过接口包扫描 -->
<!-- <package name="com.example.mapper"/> -->
</mappers>
</configuration>