MyBatis执行流程?Mybatis是否支持延迟加载?延迟加载的底层原理?
MyBatis 执行流程详解
MyBatis 的核心执行流程围绕 SQL 会话(SqlSession) 展开,通过组件协作完成数据库操作。以下是执行流程的详细步骤:
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:批量操作优化。
- Executor 类型:
3. 获取 Mapper 接口代理对象
- 动态代理机制
通过SqlSession.getMapper(Class<T> type)获取 Mapper 接口的代理对象(由MapperProxy实现)。- 代理对象将接口方法调用转换为对
SqlSession的 CRUD 操作(如selectOne、insert)。
- 代理对象将接口方法调用转换为对
4. 执行 SQL 语句
- SQL 解析与参数处理
- 匹配 SQL 语句:根据方法名或注解定位 Mapper XML 中对应的 SQL 语句(如
<select id="selectUser">)。 - 参数映射:
ParameterHandler将 Java 对象转换为 SQL 参数(支持#{}和${}占位符)。 - SQL 执行:
Executor调用StatementHandler(如PreparedStatementHandler)操作 JDBCPreparedStatement。 - 结果集映射:
ResultSetHandler将查询结果转换为 Java 对象(通过ResultMap配置或类型处理器)。
- 匹配 SQL 语句:根据方法名或注解定位 Mapper XML 中对应的 SQL 语句(如
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. 核心组件协作
- ResultLoader:负责执行延迟加载的 SQL 并填充结果。
- ProxyFactory:生成代理对象(默认使用 Javassist)。
- 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个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
作者分享
使用spring boot 3.4.4 整合knife4j 4.4.0接口文档时,在访问接口文档时可能会出现错误java.lang.NoSuchMethodError:'void org.springframework.web.method.ControllerAdviceBean.<init>(java.lang.Object)',需在配置的全局异常类前添加@Hidden即可。详情见:https://springdoc.org/#Introduction
3
HashMap的put方法的具体流程?
2
路漫漫其修远兮......
1
ArrayList和LinkedList的区别是什么?
3
什么是服务雪崩,怎么解决这个问题?
3
