Skip to content

mybatis

参考文档:The MyBatis Blog

帮助:MyBatis中文网

MyBatis 是什么

MyBatis 是一个半自动 ORM 框架。它不会像 JPA 那样把所有 SQL 都隐藏起来,而是让开发者自己编写 SQL,并负责把 SQL 参数和查询结果映射到 Java 对象。

如果要从零系统学习,先看这一页建立整体认识,再进入 MyBatis 核心全过程原理。核心页会把 Mapper 代理、SqlSessionExecutorBoundSql、参数绑定、结果映射、缓存、插件、事务和排查流程完整串起来。

它适合这些场景:

  1. 业务 SQL 比较复杂,需要开发者掌控执行细节。
  2. 团队希望 SQL 可见、可调优、可通过 explain 分析。
  3. 项目以关系型数据库为主,需要灵活处理多表查询。

执行流程

mermaid
flowchart TD
    A[Mapper 接口方法] --> B[SqlSession 代理调用]
    B --> C[读取 MappedStatement]
    C --> D[解析动态 SQL 和参数]
    D --> E[创建 PreparedStatement]
    E --> F[执行数据库 SQL]
    F --> G[ResultSet 结果集]
    G --> H[ResultMap 映射成对象]
    H --> I[返回业务代码]

核心组件

组件作用
SqlSessionFactory创建 SqlSession 的工厂
SqlSession执行 SQL、提交事务、获取 Mapper
MapperDAO 接口,业务代码主要调用它
MappedStatement一条 SQL 的完整描述,包括 SQL、参数、返回类型
Executor真正负责执行 SQL 的组件
TypeHandlerJava 类型和 JDBC 类型之间的转换
ResultMap查询结果和 Java 对象字段的映射关系

XML 和注解如何选择

方式优点缺点
XML适合复杂 SQL,结构清晰,便于维护动态 SQL文件数量更多
注解简单查询写起来快复杂 SQL 可读性差

实践中建议:

  1. 简单单表查询可以用注解或 MyBatis-Plus。
  2. 复杂查询、动态条件、多表关联优先使用 XML。
  3. 核心 SQL 保持可读,避免把大量业务判断塞进 XML。

常见能力

  1. 动态 SQL:ifchooseforeachtrim
  2. 结果映射:一对一、一对多、字段别名映射。
  3. 缓存:一级缓存默认存在,二级缓存需要谨慎开启。
  4. 插件:分页、审计、SQL 改写、性能分析。
  5. 类型处理器:处理枚举、JSON、加密字段等特殊类型。

使用建议

  1. Mapper 方法命名要表达业务语义,不要只叫 queryList
  2. 更新和删除必须带明确条件,必要时加防全表更新插件。
  3. 分页查询要关注总数 SQL 的性能。
  4. 批量写入要控制批次大小,避免单次 SQL 过大。
  5. 复杂 SQL 上线前用 explain 检查索引和扫描行数。

深入学习路线

学习顺序内容目标
1MyBatis 核心全过程原理理解 Mapper 方法到数据库返回对象的完整链路
2MyBatis 动态 SQL学会根据条件生成安全、可维护的 SQL
3MyBatis 缓存机制理解一级缓存、二级缓存和一致性风险
4MyBatis 拦截器理解分页、审计、数据权限等扩展点
5MyBatis 批量操作学会批量写入的性能边界和生产风险
6ORM 事务与一致性理解事务边界为什么应该放在 Service 层

代码 Demo:Mapper 接口和 XML

Mapper 接口:

java
public interface UserMapper {
    UserDO selectById(Long id);

    List<UserDO> selectByStatus(Integer status);
}

XML:

xml
<mapper namespace="com.example.UserMapper">
    <resultMap id="UserMap" type="com.example.UserDO">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="status" property="status"/>
    </resultMap>

    <select id="selectById" resultMap="UserMap">
        select id, username, status
        from users
        where id = #{id}
    </select>

    <select id="selectByStatus" resultMap="UserMap">
        select id, username, status
        from users
        where status = #{status}
        order by id desc
    </select>
</mapper>

重点:#{} 是预编译参数占位,能降低 SQL 注入风险;不要用字符串拼接用户输入。

为什么 MyBatis 适合 SQL 可控场景

MyBatis 的核心价值是让开发者显式控制 SQL,同时帮你完成参数绑定和结果映射。如果业务 SQL 很复杂,例如多表 join、报表查询、复杂动态条件,MyBatis 通常比全自动 ORM 更直观。

mermaid
flowchart TD
    A["Mapper 方法"] --> B["XML / 注解 SQL"]
    B --> C["参数绑定"]
    C --> D["JDBC 执行"]
    D --> E["ResultMap 映射对象"]

如果不用 #{} 而是拼接字符串,用户输入可能改变 SQL 结构,产生 SQL 注入风险。MyBatis 的底线是:业务可以灵活写 SQL,但参数必须安全绑定。