Mybatis延迟加载原理

本文解析了Mybatis中如何通过SQLSession的selectOne方法获取到代理对象,以及在调用get方法时如何实现关联对象的懒加载策略。重点介绍了`isLazy()`设置与代理对象的创建过程,以及invoke方法中对延迟加载的判断和操作。
摘要由CSDN通过智能技术生成

阶段一 调用SQLSession的查询方法时:

  1. 例如执行代码“T t = sqlSession.selecOne();”时Mybatis会返回一个T类型的代理对象,部分源码如图
 // 创建映射后的结果对象
        Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
        if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
            // 如果有内嵌的查询,并且开启延迟加载,则创建结果对象的代理对象
            final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
            for (ResultMapping propertyMapping : propertyMappings) {
                // issue gcode #109 && issue #149
                if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
                    resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
                    break;
                }
            }
        }

(由图中可以看出,其中有一段propertyMapping.isLazy(),就是我们在mapper中设置关联对象时,设置的fetchType是不是Lazy,如果是Lazy,就会创建代理对象)

阶段二 调用get方法时

  1. 执行t.get()方法时,此时实际上是会调用的代理对象的invoke()方法
  2. Mybatis的拦截器会拦截所有invoke()方法
  3. 此时会判断该方法是否设置了延迟加载,如果设置为延迟加载那么就会发送事先保存好的关联查询的SQL语句,invoke方法部分代码如图:

    if (lazyLoader.size() > 0 && !FINALIZE_METHOD.equals(methodName)) {
        // 加载所有延迟加载的属性
        if (aggressive || lazyLoadTriggerMethods.contains(methodName)) {
            lazyLoader.loadAll();
            // 如果调用了 setting 方法,则不在使用延迟加载
        } else if (PropertyNamer.isSetter(methodName)) {
            final String property = PropertyNamer.methodToProperty(methodName);
            lazyLoader.remove(property); // 移除
            // 如果调用了 getting 方法,则执行延迟加载
        } else if (PropertyNamer.isGetter(methodName)) {
            final String property = PropertyNamer.methodToProperty(methodName);
            if (lazyLoader.hasLoader(property)) {
                lazyLoader.load(property);
            }
        }
    }
  1. 接着将调用t.set()方法把查询的结果放入属性中
  2. 至此,延迟加载的属性就有了值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值