前言

一、MyBatis 概述

1. 定义与定位

MyBatis 是一款优秀的持久层框架,支持定制化 SQL、存储过程以及高级映射。
● 它消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索工作。
● 核心思想:将 SQL 语句与 Java 代码分离,通过 XML 或注解进行配置和映射。

2. 核心特点

● SQL 与代码分离:SQL 写在 XML 文件中,便于维护和优化。
● 灵活的参数映射:支持多种参数传递方式(#{}、${})。
● 强大的结果映射:支持自动映射和手动映射(resultMap),可处理复杂的关联关系。
● 动态 SQL:提供动态 SQL 标签,灵活拼接 SQL 语句。
● 缓存机制:内置一级缓存和二级缓存,提升查询性能。

3. 与 JDBC、Hibernate 的对比

对比图

二、MyBatis 核心组件

1. SqlSessionFactoryBuilder

● 作用:负责构建 SqlSessionFactory,通过读取配置文件或代码配置创建。
● 生命周期:方法级,用完即丢弃。

2. SqlSessionFactory

● 作用:创建 SqlSession 的工厂,是 MyBatis 的核心对象。
● 生命周期:应用级,整个应用运行期间只创建一次(单例模式)。

3. SqlSession

● 作用:执行 SQL、管理事务、获取 Mapper 接口的代理对象。
● 生命周期:请求/会话级,每次请求创建,用完关闭。
● 核心方法:selectOne()、selectList()、insert()、update()、delete()、commit()、rollback()。

4. Mapper 接口与 Mapper 代理

● Mapper 接口:定义数据库操作方法,无需实现类。
● Mapper 代理:MyBatis 动态生成 Mapper 接口的代理对象,负责调用 SQL 语句。
● 绑定方式:通过 XML 映射文件或注解绑定 SQL。

三、MyBatis 配置文件(mybatis-config.xml)

1. 顶层结构

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置项顺序:properties -> settings -> typeAliases -> typeHandlers -> environments -> mappers -->
</configuration>

2. 核心配置项详解

properties:引入外部属性文件(如 db.properties),用于配置数据库连接信息。

settings:全局配置项,影响 MyBatis 运行行为。
配置项 作用 示例值
cacheEnabled 开启二级缓存 true
lazyLoadingEnabled 开启延迟加载 true
mapUnderscoreToCamelCase 自动下划线转驼峰命名 true
typeAliases:为 Java 类型设置别名,简化映射文件中的类型引用。

<typeAliases>
    <typeAlias type="com.example.User" alias="User"/>
    <package name="com.example"/> <!-- 扫描包,自动设置别名(类名首字母小写) -->
</typeAliases>

environments:配置数据库环境,支持多环境切换。

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/> <!-- 事务管理器 -->
        <dataSource type="POOLED"> <!-- 数据源类型:UNPOOLED、POOLED、JNDI -->
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

mappers:注册映射文件或 Mapper 接口。

<mappers>
    <mapper resource="com/example/mapper/UserMapper.xml"/> <!-- 资源路径 -->
    <mapper class="com.example.mapper.UserMapper"/> <!-- 接口类路径 -->
    <package name="com.example.mapper"/> <!-- 扫描包 -->
</mappers>

四、MyBatis 映射文件(Mapper.xml)

1. 映射文件结构

<?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="com.example.mapper.UserMapper">
    <!-- SQL 语句定义 -->
</mapper>

2. 核心 SQL 元素

select、insert、update、delete:定义 CRUD 操作。

<select id="selectUserById" parameterType="int" resultType="User">
    SELECT * FROM user WHERE id = #{id}
</select>
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>

参数传递
#{} :预编译参数,防止 SQL 注入,推荐使用。
${}:字符串替换,存在 SQL 注入风险,仅用于动态表名、列名等场景。
结果映射
resultType:自动映射,要求数据库列名与 Java 属性名一致(或开启下划线转驼峰)。
resultMap:手动映射,处理复杂结果集和关联关系。

<resultMap id="UserResultMap" type="User">
    <id property="id" column="user_id"/> <!-- 主键映射 -->
    <result property="name" column="user_name"/> <!-- 普通属性映射 -->
    <!-- 一对一关联 -->
    <association property="dept" javaType="Dept">
        <id property="id" column="dept_id"/>
        <result property="name" column="dept_name"/>
    </association>
    <!-- 一对多关联 -->
    <collection property="orders" ofType="Order">
        <id property="id" column="order_id"/>
        <result property="amount" column="order_amount"/>
    </collection>
</resultMap>

3. 动态 SQL

if:条件判断。

<select id="selectUsers" parameterType="User" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null">AND name = #{name}</if>
        <if test="age != null">AND age = #{age}</if>
    </where>
</select>

choose、when、otherwise:多条件分支(类似 switch-case)。
trim、where、set:辅助拼接 SQL,处理多余的 AND、逗号等。
foreach:遍历集合,用于 IN 查询或批量插入。

<select id="selectUsersByIds" parameterType="list" resultType="User">
    SELECT * FROM user WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

bind:绑定变量,防止 SQL 注入或简化表达式。

五、MyBatis 核心功能

1. CRUD 操作

● 通过 Mapper 接口调用方法,或直接使用 SqlSession 执行 SQL。

2. 参数处理

单个参数:直接传递,可使用任意名称。
多个参数:使用 @Param 注解命名,或通过索引(arg0、arg1)访问。
User selectUserByNameAndAge(@Param(“name”) String name, @Param(“age”) int age);
对象参数:直接传递 Java 对象,属性名对应参数名。
Map 参数:传递 Map 集合,key 对应参数名。

3. 结果映射

自动映射:列名与属性名一致时自动映射。
手动映射:使用 resultMap 处理复杂映射、关联关系。
关联映射
○ 一对一:使用 。
○ 一对多:使用 。

4. 缓存机制

一级缓存(SqlSession 级别)
○ 默认开启,同一 SqlSession 内相同查询直接返回缓存结果。
○ 失效场景:SqlSession 关闭、执行增删改操作、手动清空缓存。
二级缓存(Mapper 级别)
○ 需手动开启,多个 SqlSession 共享同一 Mapper 的缓存。
○ 配置步骤:
ⅰ. 在 mybatis-config.xml 中开启:。
ⅱ. 在 Mapper.xml 中添加:。
○ 注意:实体类需实现 Serializable 接口。

六、MyBatis 高级特性

1. 插件开发

● 原理:通过 Interceptor 拦截 MyBatis 核心方法(Executor、ParameterHandler、ResultSetHandler、StatementHandler)。
● 自定义插件步骤:
a. 实现 Interceptor 接口。
b. 使用 @Intercepts 注解指定拦截方法。
c. 在 mybatis-config.xml 中注册插件。

2. 分页插件(PageHelper)

● 使用步骤:
a. 引入 PageHelper 依赖。
b. 在 mybatis-config.xml 中配置插件。
c. 代码中调用:PageHelper.startPage(pageNum, pageSize);。

3. 逆向工程(MyBatis Generator)

● 作用:根据数据库表自动生成实体类、Mapper 接口、Mapper.xml 文件。
● 配置:编写 generatorConfig.xml,指定数据库连接、表名、生成路径等。

4. 与 Spring/Spring Boot 整合

Spring 整合
○ 配置 SqlSessionFactoryBean、MapperScannerConfigurer。
Spring Boot 整合
○ 引入 mybatis-spring-boot-starter 依赖。
○ 在 application.yml 中配置数据源、MyBatis 配置文件路径等。

七、MyBatis-Plus(扩展)

1. 概述

MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 基础上只做增强不做改变,简化开发、提高效率。

2. 核心功能

BaseMapper:内置通用 CRUD 方法,无需编写 XML。
条件构造器(Wrapper):灵活构建查询条件(如 QueryWrapper、UpdateWrapper)。
分页插件:内置分页功能,无需额外配置。
代码生成器:一键生成实体类、Mapper、Service、Controller 代码。

八、最佳实践与常见问题

1. Mapper 接口开发规范

● Mapper 接口名与 Mapper.xml 文件名一致,且在同一包下。
● Mapper 接口方法名与 Mapper.xml 中 SQL 元素的 id 一致。
● 避免在 Mapper 接口中定义重载方法(MyBatis 无法区分)。

2. SQL 优化建议

● 避免使用 SELECT *,只查询需要的列。
● 合理使用索引,避免全表扫描。
● 批量操作使用 foreach 或批量插入 API。
● 避免在 SQL 中进行复杂计算,尽量在 Java 代码中处理。

3. 缓存使用注意事项

● 一级缓存默认开启,但在多 SqlSession 环境下可能导致数据不一致。
● 二级缓存需谨慎使用,避免缓存脏数据,建议在查询多、修改少的场景下使用。

4. 常见问题排查

● SQL 注入:避免使用 ${},尽量使用 #{} 。
● 参数绑定失败:检查参数名与 SQL 中占位符是否一致,或使用 @Param 注解。
● 结果映射失败:检查列名与属性名是否匹配,或使用 resultMap 手动映射。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐