mybatis执行sql过程

发布于:2025-05-12 ⋅ 阅读:(240) ⋅ 点赞:(0)

一、配置加载阶段​​

​​1. 读取全局配置(mybatis-config.xml)​​
  • ​​入口类​​:SqlSessionFactoryBuilder.build()
  • ​​关键组件​​:
    • XMLConfigBuilder:解析全局配置文件。
    • Configuration:存储所有配置信息(数据源、映射器、插件等)。
  • ​​过程​​:
    • 解析 <environments> 标签,创建 DataSource 和 TransactionFactory。
    • 解析 <mappers> 标签,加载 Mapper XML 或接口。
​​2. 加载 Mapper 文件(UserMapper.xml)​​
  • ​​入口类​​:XMLMapperBuilder.parse()
  • ​​关键组件​​:
    • MappedStatement:每个 SQL 操作的抽象(包含 SQL 文本、参数映射、结果映射等)。
    • SqlSource:动态 SQL 或静态 SQL 的封装。
  • ​​过程​​:
    • 解析 <select|insert|update|delete> 标签,生成 MappedStatement。
    • 解析动态 SQL(如 <if>, <foreach>),生成 SqlNode 语法树。
​ ​二、会话创建阶段​​
​​1. 创建 SqlSessionFactory​​
  • ​​实现类​​:DefaultSqlSessionFactory
  • ​​作用​​:生产 SqlSession(数据库操作入口)。
​​2. 创建 SqlSession​​
  • ​​核心方法​​:openSession()
  • ​​关键组件​​:
    • Executor:执行 SQL 的核心组件(默认实现为 SimpleExecutor)。
    • Transaction:事务管理器(JDBC 或 MANAGED)。

​​三、SQL 解析阶段

​​1. Mapper 接口代理​​
  • ​​入口​​:sqlSession.getMapper(UserMapper.class)
  • ​​关键组件​​:
    • MapperProxy:动态代理类,拦截接口方法调用。
    • MapperMethod:将方法调用转换为 SQL 操作(SELECT|INSERT|UPDATE|DELETE)。
​​2. 生成 BoundSql​​
  • ​​关键组件​​:
    • SqlSource:通过 DynamicSqlSource 或 RawSqlSource 解析 SQL。
    • BoundSql:最终可执行的 SQL + 参数映射信息。
  • ​​过程​​:
    • 替换 ${} 占位符(直接文本替换)。
    • 解析 #{} 占位符,生成 ? 并记录参数映射关系。
​ ​四、参数处理阶段​​
​​1. 参数绑定​​
  • ​​关键组件​​:
    • ParameterHandler(实现类:DefaultParameterHandler)
    • TypeHandler:类型转换处理器(如 StringTypeHandler、DateTypeHandler)。
  • ​​过程​​:
    • 根据 MappedStatement 中的参数映射(ParameterMapping)解析参数。
    • 使用 TypeHandler 将 Java 对象转换为 JDBC 类型。
    • 通过 PreparedStatement.setXXX() 设置参数。
​​2. 动态 SQL 处理​​
  • ​​示例​​:
<select id="findUsers"> 
    SELECT * FROM users 
    <where> 
    <if test="name != null">AND name = #{name}</if> 
    <if test="age > 18">AND age = #{age}</if> 
    </where> 
</select>
  • ​解析器​​:XMLScriptBuilder 将 <if> 转换为 IfSqlNode。
  • ​​执行逻辑​​:运行时根据参数值动态拼接 SQL。
​ ​五、SQL 执行阶段​​
​​1. 执行器(Executor)工作流程​​
  • ​​核心类​​:BaseExecutor → SimpleExecutor(默认)
  • ​​流程​​:
    • 检查一级缓存(LocalCache)是否存在结果。
    • 未命中缓存时,创建 StatementHandler。
    • 调用 StatementHandler.prepare() 创建 Statement 对象。
    • 执行 StatementHandler.query() 或 update()。
​​2. StatementHandler 的类型​​

类型

说明

SimpleStatementHandler

处理普通Statement(无参数)

PreparedStatementHandler

处理PreparedStatement(预编译,推荐)

CallableStatementHandler

处理存储过程调用

​​3. 执行细节​​
  • ​​预编译优化​​:
// 生成 PreparedStatement 
Connection conn = session.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
// 设置参数 
parameterHandler.setParameters(ps); 
// 执行查询 
ResultSet rs = ps.executeQuery();

​ ​六、结果映射阶段​​
​​1. 结果集处理​​
  • ​​关键组件​​:
    • ResultSetHandler(实现类:DefaultResultSetHandler)
    • ResultMap:定义结果集与 Java 对象的映射规则。
  • ​​过程​​:
    • 遍历 ResultSet 的每一行。
    • 根据 ResultMap 创建目标对象(如 User)。
    • 使用 TypeHandler 将数据库字段值填充到对象属性。
​​2. 嵌套映射与延迟加载​​
  • ​​嵌套查询​​:
<resultMap id="userWithOrders" type="User"> 
    <collection property="orders" column="id" select="selectOrdersByUserId"/> 
</resultMap>
  • ​触发时机​​:访问 user.getOrders() 时执行子查询(需开启延迟加载)。

​​七、核心组件协作流程图​​

​​八、高级特性扩展​​

​​1. 插件机制(Interceptor)​​
  • ​​拦截点​​:Executor、StatementHandler、ParameterHandler、ResultSetHandler。
  • ​​应用场景​​:分页插件、性能监控、SQL 改写。
​​2. 二级缓存​​
  • ​​作用范围​​:Mapper 级别,跨 SqlSession 共享。
  • ​​启用条件​​:在 Mapper XML 中添加  标签。
​​3. 延迟加载​​
  • ​​配置​​:在 mybatis-config.xml 中设置:
<settings>
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

通过理解 MyBatis 的执行原理,可以更好地优化 SQL 性能、定制插件,并快速定位复杂问题(如缓存失效、动态 SQL 错误等)。


微信公众号

今日签到

点亮在社区的每一天
去签到