MyBatis的执行流程

解释:

这是xml格式的MyBatis的配置文件

追踪MyBatis的执行过程中的参数

MyBatis 是一个优秀的持久层框架,它通过 XML 或注解的方式将 SQL 语句与 Java 对象进行映射,简化了 JDBC 的操作。理解 MyBatis 的执行流程,有助于掌握其底层原理,提升开发效率和排查问题能力。


🌟 一、MyBatis 执行流程概览(以 select 为例)

1. 加载配置并初始化 SqlSessionFactory
2. 创建 SqlSession
3. 获取 Mapper 接口代理对象
4. 调用 Mapper 方法
5. 执行 SQL:解析 SQL、参数处理、执行、结果映射
6. 返回结果
7. 提交或关闭 SqlSession

🔍 二、详细执行流程(图解 + 说明)

✅ 阶段1:初始化 —— 创建 SqlSessionFactory

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
流程:
  1. 读取 mybatis-config.xml 主配置文件(数据源、事务、Mapper 映射文件位置等)
  2. 读取 <mappers> 中的 SQL 映射文件(如 UserMapper.xml
  3. 解析 SQL 映射文件,构建 MappedStatement 对象(封装 SQL、参数类型、返回类型等)
  4. 创建 SqlSessionFactory(工厂模式,用于创建 SqlSession

📌 SqlSessionFactory 是线程安全的,通常整个应用只有一个实例。


✅ 阶段2:获取 SqlSession

SqlSession sqlSession = sqlSessionFactory.openSession();
  • SqlSession 是 MyBatis 的核心接口,代表一次数据库会话。
  • 封装了所有执行 SQL 的方法:selectOne()selectList()insert()update()delete() 等。
  • 不是线程安全,每次请求应创建或从线程池获取。

✅ 阶段3:获取 Mapper 代理对象

UserMapper mapper = sqlSession.getMapper(UserMapper.class);
MyBatis 做了什么?
  • 使用 JDK 动态代理,为 UserMapper 接口生成代理对象。
  • 代理逻辑:拦截接口方法调用,根据方法名找到对应的 SQL 语句(namespace + id)。

📌 例如:UserMapper.selectById(id)com.example.mapper.UserMapper.selectById


✅ 阶段4:执行 SQL(核心流程)

当你调用:

User user = mapper.selectById(1L);

MyBatis 内部执行流程如下:

🔁 4.1 根据方法名查找 MappedStatement

  • 通过接口全限定名 + 方法名,找到对应的 MappedStatement(在初始化时已加载)
<!-- UserMapper.xml -->
<select id="selectById" resultType="User">
  SELECT * FROM user WHERE id = #{id}
</select>

→ 找到 MappedStatement,包含:

  • SQL 语句
  • 参数类型
  • 返回类型
  • 执行器类型等

🔁 4.2 参数处理(ParameterHandler)

  • 将方法参数(如 1L)封装成 BoundSql
  • 处理 #{} 和 ${}
    • #{id} → 预编译占位符 ?,防止 SQL 注入
    • ${id} → 字符串拼接,需谨慎使用
  • 生成最终 SQL:SELECT * FROM user WHERE id = ?

🔁 4.3 执行 SQL(Executor + StatementHandler)

  • Executor(执行器):负责 SQL 执行和一级缓存
    • SimpleExecutor:默认,每次重新 prepare
    • ReuseExecutor:重用 Statement
    • BatchExecutor:批量执行
  • StatementHandler:使用 JDBC 的 PreparedStatement 执行 SQL
    • 设置参数
    • 执行 executeQuery() 或 executeUpdate()

🔁 4.4 结果映射(ResultSetHandler)

  • 获取 ResultSet
  • 根据 resultType 或 resultMap 进行映射:
    • 简单类型:直接返回(如 intString
    • POJO 类型:通过反射创建对象,设置字段值
    • 复杂映射:处理一对一、一对多(嵌套查询或嵌套结果)
// 自动映射:列名 → 属性名(支持驼峰转下划线)
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
// ...

✅ 阶段5:返回结果

  • 将映射后的结果返回给调用方
  • selectOne() → 单个对象
  • selectList() → List
  • insert() → 影响行数

✅ 阶段6:事务提交与关闭

// 如果是手动提交模式,需要显式提交
sqlSession.commit();
// 关闭资源
sqlSession.close();

🧩 三、核心组件关系图

SqlSessionFactoryBuilder
        ↓
SqlSessionFactory ——(唯一)——→ Configuration
        ↓
   SqlSession ——(每次请求)——→ Executor ——→ StatementHandler
        ↓                             ↓              ↓
    Mapper Proxy                ParameterHandler   ResultSetHandler
        ↓
   调用方法 → 触发执行

🔁 四、一级缓存 & 二级缓存

1. 一级缓存(Local Cache)

  • 默认开启,基于 SqlSession
  • 同一个 SqlSession 中,相同 SQL 和参数会从缓存中取结果
  • 在 commit() 或 close() 时清空

2. 二级缓存(Global Cache)

  • 基于 namespace(Mapper 接口)
  • 需要手动开启:<cache/> 或 @CacheNamespace
  • 跨 SqlSession 共享,需序列化支持

✅ 五、使用注解时的流程

MyBatis 也支持注解方式:

@Select("SELECT * FROM user WHERE id = #{id}")
User selectById(Long id);

流程基本一致,只是:

  • SQL 从 XML 改为注解解析
  • 初始化时通过反射读取注解,构建 MappedStatement

✅ 六、与 Spring 集成时的变化

在 Spring 中使用 MyBatis(如 mybatis-spring):

  • SqlSessionFactory 由 Spring 容器管理
  • Mapper 接口通过 @MapperScan 自动注册为 Bean
  • 不用手动获取 SqlSession,直接 @Autowired 注入 Mapper
  • 事务由 Spring 的 @Transactional 管理

✅ 七、总结:MyBatis 执行流程口诀

🎯 “一工二会三代理,四找五参六执行,七映八果九关闭。”

步骤说明
一工创建 SqlSessionFactory
二会获取 SqlSession
三代理获取 Mapper 代理对象
四找根据方法名找 MappedStatement
五参参数处理 → BoundSql
六执行Executor 执行 SQL
七映ResultSetHandler 结果映射
八果返回结果
九关闭提交事务,关闭 SqlSession

💡 最佳实践建议

  1. 优先使用 #{} 防止 SQL 注入
  2. 复杂映射使用 resultMap,简单用 resultType
  3. 合理使用一级/二级缓存提升性能
  4. Mapper 接口与 XML 文件保持命名一致
  5. 在 Spring 中使用 @Mapper 或 @MapperScan

掌握 MyBatis 的执行流程,你就能真正理解它“半自动化”ORM 的魅力!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值