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> constructorArgTypes = new ArrayList>();
    final List constructorArgs = new ArrayList();
    final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
    //comment by jerry
//        if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
//      final List 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> constructorArgTypes, List 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> constructorArgTypes, List 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







你可能感兴趣的:(mybatis源代码分析:mybatis延迟加载机制改进)