mybatis工作原理及流程 mybatis延迟加载原理

1. 目的
本文主要解读MyBatis 延迟加载实现原理
2. 延迟加载如何使用
Setting 参数配置
设置参数描述有效值默认值lazyLoadingEnabled延迟加载的全局开关 。当开启时 , 所有关联对象都会延迟加载 。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态 。true、
falsefalseaggressiveLazyLoading当开启时 , 任何方法的调用都会加载该对象的所有属性 。否则 , 每个属性会按需加载(参考lazyLoadTriggerMethods).true、falsefalse (true in ≤3.4.1)lazyLoadTriggerMethods指定哪个对象的方法触发一次延迟加载 。用逗号分隔的方法列表 。equals,clone,hashCode,toString
配置
<configuration> <settings> <!-- 开启延迟加载 --> <setting name="lazyLoadingEnabled" value="https://www.jinnalai.com/fenxiang/true" /> <setting name="aggressiveLazyLoading" value="https://www.jinnalai.com/fenxiang/false" /> <setting name="lazyLoadTriggerMethods" value="https://www.jinnalai.com/fenxiang/equals,clone,hashCode,toString" /> </settings></configuration>Mapper 配置
<mapper namespace="org.apache.ibatis.submitted.lazy_properties.Mapper"><resultMap type="org.apache.ibatis.submitted.lazy_properties.User" id="user"> <id property="id" column="id" /> <result property="name" column="name" /> </resultMap> <!-- 结果对象 --> <resultMap type="org.apache.ibatis.submitted.lazy_properties.User" id="userWithLazyProperties" extends="user"> <!-- 延迟加载对象lazy1 --> <association property="lazy1" column="id" select="getLazy1" fetchType="lazy" /> <!-- 延迟加载对象lazy2 --> <association property="lazy2" column="id" select="getLazy2" fetchType="lazy" /> <!-- 延迟加载集合lazy3 --><collection property="lazy3" column="id" select="getLazy3" fetchType="lazy" /> </resultMap> <!-- 执行的查询 --> <select id="getUser" resultMap="userWithLazyProperties"> select * from users where id = #{id} </select></mapper>User 实体对象
public class User implements Cloneable { private Integer id; private String name; private User lazy1; private User lazy2; private List<User> lazy3; public int setterCounter;省略... }执行解析:

  • 调用getUser查询数据 , 从查询结果集解析数据到User对象 , 当数据解析到lazy1 , lazy2 , lazy3判断需要执行关联查询
  • lazyLoadingEnabled=true , 将创建lazy1 , lazy2 , lazy3对应的Proxy延迟执行对象lazyLoader , 并保存
  • 当逻辑触发lazyLoadTriggerMethods 对应的方法(equals,clone,hashCode,toString)则执行延迟加载
  • 如果aggressiveLazyLoading=true , 只要触发到对象任何的方法 , 就会立即加载所有属性的加载
3. 延迟加载原理实现
延迟加载主要是通过动态代理的形式实现 , 通过代理拦截到指定方法 , 执行数据加载 。
MyBatis延迟加载主要使用:Javassist , Cglib实现 , 类图展示:
mybatis工作原理及流程 mybatis延迟加载原理


4. 延迟加载源码解析
Setting 配置加载:
public class Configuration {/** aggressiveLazyLoading: * 当开启时 , 任何方法的调用都会加载该对象的所有属性 。否则 , 每个属性会按需加载(参考lazyLoadTriggerMethods). * 默认为true * */ protected boolean aggressiveLazyLoading; /** * 延迟加载触发方法 */ protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" })); /** 是否开启延迟加载 */ protected boolean lazyLoadingEnabled = false;/** * 默认使用Javassist代理工厂 * @param proxyFactory */ public void setProxyFactory(ProxyFactory proxyFactory) { if (proxyFactory == null) { proxyFactory = new JavassistProxyFactory(); } this.proxyFactory = proxyFactory; }//省略...}

推荐阅读