mybatis源代码分析:mybatis延迟加载机制改进

在上一篇博客 mybatis源代码分析:深入了解mybatis延迟加载机制》讲诉了mybatis延迟加载的具体机制及实现原理。

可以看出,如果查询结果对象中有一个属性是需要延迟加载的,那整个结果对象就被替换为一个代理对象,后面对这个对象的访问,都是通过代理对象去访问的,那是否有更好的方法呢?

答案是有的,具体如下:

Student对象关联Teacher对象,需要对Teacher对象延迟加载。

一种方式就是mybatis当前的这种做法,对Student进行代理,当访问到getTeacher时就进行延迟加载,设置其teacher对象;

还有一种方式就是对teacher对象进行代理,当第一次加载之后,就将Student对象关联的teacher对象替换为真实的对象,而不再使用代理对象,这样后面对Student及Teacher的访问,就都是访问的实际对象,而不是代理对象了。

修改之后的代码:http://download.csdn.net/detail/u014569459/7372195


关键修改点说明(基于mybatis 3.2.7 版本修改):

1.修改org\apache\ibatis\executor\resultset\DefaultResultSetHandler.java类,注销掉里面生成代理对象的代码

  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
    final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
    final List<Object> constructorArgs = new ArrayList<Object>();
    final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
    //comment by jerry
//        if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
//      final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
//      for (ResultMapping propertyMapping : propertyMappings) {
//        if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { // issue gcode #109 && issue #149
//          return configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
//        }
//      }
//    }
    return resultObject;
  }

2.修改org\apache\ibatis\executor\loader\cglib\CglibProxyFactory.java类

1)在createProxy方法增加两个参数Object parentObj,String fieldNameInParent,用于访问父对象。

  public Object createProxy(Object parentObj,String fieldNameInParent,Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    return EnhancedResultObjectProxyImpl.createProxy(parentObj,fieldNameInParent,target, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
  }

2)在EnhancedResultObjectProxyImpl类中,增加parentObj和属性,并修改默认构造函数。

    private Object parentObj;
    private String fieldNameInParent;

    private EnhancedResultObjectProxyImpl(Object parentObj,String fieldNameInParent,Class<?> type, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
      this.type = type;
      this.lazyLoader = lazyLoader;
      this.aggressive = configuration.isAggressiveLazyLoading();
      this.lazyLoadTriggerMethods = configuration.getLazyLoadTriggerMethods();
      this.objectFactory = objectFactory;
      this.constructorArgTypes = constructorArgTypes;
      this.constructorArgs = constructorArgs;
      this.parentObj = parentObj;
      this.fieldNameInParent = fieldNameInParent;
    }

3)修改intercept函数

        if(parentObj!=null)
        {
            Field field = parentObj.getClass().getDeclaredField(fieldNameInParent);
            Object obj = field.get(parentObj);
            return method.invoke(obj, args);
        }
        else
        {
        	return methodProxy.invokeSuper(enhanced, args);	
        }


修改文件列表(共4个):

完整代码链接:https://code.csdn.net/snippets/355671

1.CglibProxyFactory.java

2.JavassistProxyFactory.java

3.ProxyFactory.java

4.DefaultResultSetHandler.java






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值