Skip to content

MyBatis 概述与架构

  MyBatis 的前身是 Apache 的开源项目 iBatis,2010 年迁移到 Google Code 并更名为 MyBatis,2013 年迁移到 GitHub。它是一款持久层框架,封装了 JDBC 的操作,让开发者只需关注 SQL 本身。

一、MyBatis 是什么?

一句话:
  MyBatis = SQL 映射框架 + 半自动 ORM
  让你自由写 SQL,同时自动帮你搞定参数绑定和结果映射

核心能力:

① 解耦 SQL 与 Java 代码
  SQL 写在 XML 配置文件中,修改 SQL 不需要重新编译

② 自动映射
  查询结果自动映射为 Java 对象(POJO)

③ 动态 SQL
  根据条件动态拼接 SQL,告别 Java 里的字符串拼接

④ 数据库连接池
  内置连接池,自动管理连接的获取和释放

⑤ 缓存支持
  一级缓存(SqlSession 级别)+ 二级缓存(Mapper 级别)

二、架构设计

MyBatis 架构分层:

┌─────────────────────────────────────────────────────┐
│                    接口层(API)                     │
│  SqlSession  →  增删改查、提交回滚、获取 Mapper      │
└──────────────────────┬──────────────────────────────┘

┌──────────────────────▼──────────────────────────────┐
│                   数据处理层                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐      │
│  │ 参数映射  │  │ SQL 解析  │  │  结果映射     │      │
│  │parameter  │  │  dynamic  │  │  result      │      │
│  │  mapping  │  │   SQL     │  │  mapping     │      │
│  └──────────┘  └──────────┘  └──────────────┘      │
└──────────────────────┬──────────────────────────────┘

┌──────────────────────▼──────────────────────────────┐
│                   基础支撑层                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐      │
│  │ 连接池    │  │ 事务管理  │  │  缓存模块     │      │
│  │ Pooled   │  │   Tx     │  │   Cache      │      │
│  └──────────┘  └──────────┘  └──────────────┘      │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐      │
│  │ 日志模块  │  │ 反射模块  │  │  配置解析     │      │
│  │ Logging  │  │Reflector │  │  XMLConfig   │      │
│  └──────────┘  └──────────┘  └──────────────┘      │
└─────────────────────────────────────────────────────┘

三、核心组件

3.1 SqlSessionFactory

作用:创建 SqlSession 的工厂,全局唯一,应用启动时创建

内部持有:
  ├─ Configuration(全局配置对象)
  ├─ 所有 Mapper 的映射信息
  └─ 数据库环境配置

创建方式:
  SqlSessionFactory sqlSessionFactory =
      new SqlSessionFactoryBuilder().build(inputStream);

3.2 SqlSession

作用:执行 SQL、获取 Mapper、管理事务的会话对象

生命周期:
  ├─ 非线程安全 → 每个线程独立使用
  ├─ 每次请求创建 → 用完关闭
  └─ 是请求/方法级别的作用域

核心方法:
  selectOne / selectList   → 查询
  insert / update / delete → 增删改
  commit / rollback        → 事务控制
  getMapper                → 获取 Mapper 代理对象
  close                    → 关闭会话

3.3 Mapper 接口

作用:定义 SQL 操作的接口,MyBatis 动态代理生成实现

绑定方式:
  ① XML 映射:namespace = 接口全限定名
  ② 注解映射:@Select / @Insert / @Update / @Delete

示例:
  public interface UserMapper {
      User selectById(Long id);
  }

3.4 Executor(执行器)

作用:真正执行 SQL 的核心组件,SqlSession 内部委托给 Executor

三种类型:
  SIMPLE   → 简单执行器(默认),每次执行都创建新的 PreparedStatement
  REUSE    → 可重用执行器,缓存 PreparedStatement
  BATCH    → 批量执行器,用于批量操作

配置方式:
  <settings>
      <setting name="defaultExecutorType" value="REUSE"/>
  </settings>

四、工作原理(完整执行流程)

用户代码                        MyBatis 内部

orderMapper.insert(order);


┌─────────────────────────────────────────────────────────┐
│ ① MapperProxy(动态代理拦截)                            │
│    → 拦截接口方法调用                                     │
│    → 根据方法名找到对应的 MappedStatement                  │
└──────────────────────────┬──────────────────────────────┘

┌──────────────────────────▼──────────────────────────────┐
│ ② SqlSession(会话层)                                   │
│    → insert/update/delete/select                         │
│    → 委托给 Executor 执行                                │
└──────────────────────────┬──────────────────────────────┘

┌──────────────────────────▼──────────────────────────────┐
│ ③ Executor(执行器)                                     │
│    → 处理缓存(一级/二级缓存)                             │
│    → 创建 StatementHandler                              │
└──────────────────────────┬──────────────────────────────┘

┌──────────────────────────▼──────────────────────────────┐
│ ④ StatementHandler(语句处理器)                         │
│    → ParameterHandler:参数绑定(?占位符赋值)             │
│    → 执行 SQL(jdbc PreparedStatement.execute())         │
│    → ResultSetHandler:结果映射(ResultSet → Java 对象)   │
└─────────────────────────────────────────────────────────┘

速记:

一次 SQL 执行经过了 5 层:
  接口代理 → SqlSession → Executor → StatementHandler → JDBC

五、与 JDBC 的对比

步骤JDBCMyBatis
加载驱动Class.forName()配置文件指定
获取连接DriverManager.getConnection()自动从连接池获取
创建 StatementConnection.createStatement()自动创建
设置参数stmt.setString(1, value)自动映射(#{} 占位符)
执行 SQLstmt.executeQuery()自动执行
处理结果while(rs.next())自动映射到对象
关闭资源rs.close() stmt.close() conn.close()自动关闭
java
// JDBC 方式(繁琐)
public User findById(Long id) {
    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;
    try {
        conn = DriverManager.getConnection(url, user, password);
        stmt = conn.prepareStatement("SELECT * FROM user WHERE id = ?");
        stmt.setLong(1, id);
        rs = stmt.executeQuery();
        if (rs.next()) {
            User user = new User();
            user.setId(rs.getLong("id"));
            user.setName(rs.getString("name"));
            user.setAge(rs.getInt("age"));
            return user;
        }
        return null;
    } catch (SQLException e) {
        throw new RuntimeException(e);
    } finally {
        if (rs != null) try { rs.close(); } catch (SQLException ignored) {}
        if (stmt != null) try { stmt.close(); } catch (SQLException ignored) {}
        if (conn != null) try { conn.close(); } catch (SQLException ignored) {}
    }
}

// MyBatis 方式(简洁)
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User findById(Long id);
}

六、面试要点

问题答案要点
MyBatis 是什么?半自动 ORM 持久层框架,SQL 与 Java 分离
核心组件有哪些?SqlSessionFactory、SqlSession、Mapper、Executor
SqlSession 生命周期?非线程安全,请求级别,用完关闭
执行流程是怎样的?MapperProxy → SqlSession → Executor → StatementHandler → JDBC
和 Hibernate 的区别?MyBatis 手写 SQL 更灵活,Hibernate 全自动映射