MyBatis执行流程?Mybatis是否支持延迟加载?延迟加载的底层原理?


MyBatis 执行流程详解

MyBatis 的核心执行流程围绕 SQL 会话(SqlSession) 展开,通过组件协作完成数据库操作。以下是执行流程的详细步骤:

image (5).png

1. 创建 SqlSessionFactory

  • 解析配置文件
    通过 SqlSessionFactoryBuilder 读取 MyBatis 全局配置文件(mybatis-config.xml)和 Mapper XML 文件,生成 Configuration 对象,包含所有配置信息(如数据源、类型处理器、Mapper 接口与 SQL 映射关系等)。
  • 构建工厂
    基于 Configuration 创建 SqlSessionFactory(默认实现为 DefaultSqlSessionFactory),用于后续创建 SqlSession

2. 创建 SqlSession

  • 获取会话实例
    调用 SqlSessionFactory.openSession() 创建 SqlSession,内部通过 事务工厂(TransactionFactory)执行器(Executor) 管理数据库连接与事务。
    • Executor 类型
      • SimpleExecutor:默认执行器,每执行一次 SQL 开启一个 Statement。
      • ReuseExecutor:重用预处理 Statement。
      • BatchExecutor:批量操作优化。

3. 获取 Mapper 接口代理对象

  • 动态代理机制
    通过 SqlSession.getMapper(Class<T> type) 获取 Mapper 接口的代理对象(由 MapperProxy 实现)。
    • 代理对象将接口方法调用转换为对 SqlSession 的 CRUD 操作(如 selectOneinsert)。

4. 执行 SQL 语句

  • SQL 解析与参数处理
    1. 匹配 SQL 语句:根据方法名或注解定位 Mapper XML 中对应的 SQL 语句(如 <select id="selectUser">)。
    2. 参数映射ParameterHandler 将 Java 对象转换为 SQL 参数(支持 #{}${} 占位符)。
    3. SQL 执行Executor 调用 StatementHandler(如 PreparedStatementHandler)操作 JDBC PreparedStatement
    4. 结果集映射ResultSetHandler 将查询结果转换为 Java 对象(通过 ResultMap 配置或类型处理器)。

5. 提交事务与关闭资源

  • 事务提交
    若未启用自动提交(默认关闭),需手动调用 SqlSession.commit()
  • 释放连接
    关闭 SqlSession,释放数据库连接(返回到连接池)。

MyBatis 是否支持延迟加载?

✅ 支持延迟加载(Lazy Loading)
MyBatis 的延迟加载主要用于处理 关联对象(如一对一、一对多查询),只有在实际访问关联对象时才会触发 SQL 查询,避免一次性加载所有数据。


延迟加载的底层原理

1. 配置启用延迟加载

在 MyBatis 全局配置中开启延迟加载:

xml
复制代码
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> <!-- 禁止激进加载 --> </settings>

或在关联映射中指定 fetchType="lazy"

xml
复制代码
<association property="department" column="dept_id" select="com.example.mapper.DepartmentMapper.selectById" fetchType="lazy"/>

2. 延迟加载的实现机制

  • 动态代理生成代理对象
    当查询主对象(如 User)时,MyBatis 会为关联对象(如 Department)生成一个 代理对象(通过 Javassist 或 CGLIB),而非真实对象。

    • 代理对象拦截所有方法调用(如 getDepartment())。
  • 触发实际查询
    当首次调用代理对象的方法时,代理逻辑会通过 SqlSession 执行关联 SQL(如 selectById),完成关联对象的加载,并替换代理对象为真实对象。

  • 会话一致性要求
    延迟加载需保证 原 SqlSession 未关闭(否则会抛出异常),因此通常与 一级缓存(SqlSession 级别缓存)配合使用。


3. 核心组件协作

  1. ResultLoader:负责执行延迟加载的 SQL 并填充结果。
  2. ProxyFactory:生成代理对象(默认使用 Javassist)。
  3. LazyLoader:封装延迟加载逻辑,绑定到代理对象。

延迟加载的示例场景

java
复制代码
User user = userMapper.selectUserById(1); // 此时仅加载 User 数据,Department 未被查询 Department dept = user.getDepartment(); // 触发延迟加载,执行 DepartmentMapper.selectById 查询部门数据

总结

机制说明
执行流程从 SqlSessionFactory 创建到 SQL 执行,核心组件包括 Executor、StatementHandler 等。
延迟加载支持通过动态代理实现按需加载关联对象,减少不必要的数据库查询。
代理对象触发时机首次访问关联对象的方法时触发 SQL 查询。
注意事项需确保 SqlSession 在访问延迟对象时未关闭,避免 LazyInitializationException

通过合理使用延迟加载,可以优化复杂查询性能,但需注意 N+1 查询问题 和会话生命周期管理。

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
李南北
下载 APP