`
xdy2008
  • 浏览: 52724 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

ibatis延迟加载

阅读更多
  所谓的延迟加载,就是将暂时不需要的对象不真正的载人内存,直到真正需要的时候再去执行加载动作。在iBatis中,实现延迟加载的思路:如果一个对象的某个属性需要被延迟加载,那么首先创建这个属性对应的代理对象并返回;当真正使用时,调用这个代理对象的相关方法,invoke方法得以执行,此时,在invoke方法里面,去执行真正的加载操作。

     总结起来,对于延迟加载,首先创建一个被延迟加载对象的代理对象,当使用代理对象时,就是真正需要加载的时刻,在执行invoke方法时执行加载。

     在iBatis中,延迟加载相关的类主要有:ResultLoader,LazyResultLoader,EnhancedLazyResultLoader。其中ResultLoader是执行数据加载的类,LazyResultLoader和EnhancedResultLoader是延迟加载的的实现类,LazyResultLoader使用的是java的代理模型,EnhancedResultLoader使用的是cglib。

     那么,在iBatis中,延迟加载是如何实现的呢?

     在iBatis中,在RowMap中,如果某个result属性中指定了select属性,那么此处就有可能会发生延迟加载。在处理ResultMap时,ResultMap类中的getNestedSelectMappingValue方法会触发ResultLoader的loadResult方法。下面,就先看一下loadResult是如何实现的。

view plaincopy to clipboardprint?

    public static Object loadResult(SqlMapClientImpl client, String statementName, Object parameterObject, Class targetType) 
        throws SQLException { 
      Object value = null; 
     
      //如果需要延迟加载,在SqlMapConfig中的setting中指定 
      if (client.isLazyLoadingEnabled()) { 
        //如果使用基于cglib的增强性能的延迟加载,需要SqlMapConfig中的setting中指定 
        if (client.isEnhancementEnabled()) { 
          EnhancedLazyResultLoader lazy = new EnhancedLazyResultLoader(client, statementName, parameterObject, targetType); 
          value = lazy.loadResult(); 
        } else { 
          //使用基于jdk反射的延迟加载 
          LazyResultLoader lazy = new LazyResultLoader(client, statementName, parameterObject, targetType); 
          value = lazy.loadResult(); 
        } 
      } else { 
        //不使用延迟加载 
        value = getResult(client, statementName, parameterObject, targetType); 
      } 
     
      return value; 
    } 

      在上述代码中,根据setting中指定的enhancementEnabled和lazyLoadingEnabled属性来决定是否使用延迟加载以及使用延迟加载的策略,分别创建了LazyResultLoader和EnhancedLazyResultLoader对象,并且调用了loadResult方法,下面就分别看一下这两个类中的loadResult是如何实现的。

     首先看一下LazyResultLoader的loadResult实现

view plaincopy to clipboardprint?

    public Object loadResult() throws SQLException { 
      //注意,只代理Collection。也就是说非Collection类型的属性不会被延迟加载 
      if (Collection.class.isAssignableFrom(targetType)) { 
        InvocationHandler handler = new LazyResultLoader(client, statementName, parameterObject, targetType); 
        ClassLoader cl = targetType.getClassLoader(); 
        if (Set.class.isAssignableFrom(targetType)) { 
          //创建Set类型的代理对象 
          return Proxy.newProxyInstance(cl, SET_INTERFACES, handler); 
        } else { 
          //创建List类型的代理对象 
          return Proxy.newProxyInstance(cl, LIST_INTERFACES, handler); 
        } 
      } else { 
        //不执行延迟加载,直接加载数据 
        return ResultLoader.getResult(client, statementName, parameterObject, targetType); 
      } 
    } 

    根据上述代码可知,使用基于java反射的延迟加载实现,只会延迟加载那些类型为Collection的属性,其他属性即使配置为延迟加载也会被立即载入内存的。

    然后看一下EnhancedLazyResultLoader的loadResult实现。

view plaincopy to clipboardprint?

    public Object loadResult() throws SQLException { 
       
      if (DomTypeMarker.class.isAssignableFrom(targetType)) { 
        //这个DomTypeMarker不太清楚是干什么的 
        return ResultLoader.getResult(client, statementName, parameterObject, targetType); 
      } else if (Collection.class.isAssignableFrom(targetType)) { 
        //延迟加载集合类 
        if (Set.class.isAssignableFrom(targetType)) { 
          return Enhancer.create(Object.class, SET_INTERFACES, this); 
        } else { 
          return Enhancer.create(Object.class, LIST_INTERFACES, this); 
        } 
      } else if (targetType.isArray() || ClassInfo.isKnownType(targetType)) { 
        //数组类型和其他的集合类型,以及一些iBATIS定义的简单类型不延迟加载 
        return ResultLoader.getResult(client, statementName, parameterObject, targetType); 
      } else { 
        //其他情况下延迟加载 
        return Enhancer.create(targetType, this); 
      } 
    } 

   根据上述代码可知,采用了cglib创建代理对象的技术,而且被延迟加载的属性类型与LazyResultLoader中不同。如自定义类型的属性,在LazyResultLoader中不会被延迟加载,在EnhancedLazyResultLoader中会被延迟加载。究其根本原因在于:Java反射代理只能代理接口对象,而cglib的代理对象是基于asm的字节码增强技术,可以代理接口和对象。

   在创建完了代理对象后,就是当请求真正发生时,代理对象如何处理?如何加载所需数据?下面就来看一下代理对象的invoke方法。

view plaincopy to clipboardprint?

    public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 
       
      if ("finalize".hashCode() == method.getName().hashCode() 
          && "finalize".equals(method.getName())) { 
        //处理finalize方法 
        return null; 
      } else { 
        //执行真正的加载数据操作 
        loadObject(); 
        if (resultObject != null) { 
          try { 
            //客户对象向代理对象发出请求,代理对象将请求转发给已被加载出来的对象 
            return method.invoke(resultObject, objects); 
          } catch (Throwable t) { 
            throw ClassInfo.unwrapThrowable(t); 
          } 
        } else { 
          return null; 
        } 
      } 
    } 
     
    private synchronized void loadObject() { 
      if (!loaded) { 
        try { 
          loaded = true; 
          resultObject = ResultLoader.getResult(client, statementName, parameterObject, targetType); 
        } catch (SQLException e) { 
          throw new RuntimeException("Error lazy loading result. Cause: " + e, e); 
        } 
      } 
    } 

 

     经过上述的讲解,结合代码,可以比较深入的理解iBATIS延迟加载的实现机制。下面对以上内容做一个简短的总结:

     延迟加载的核心思想是动态代理模式。首先并不加载数据,而是创建一个代理对象,需要数据的时候由代理对象去加载所需数据。iBatis中有两种延迟加载的方法:基于java反射的LazyResultLoader和基于cglib的EnhancedLazyResultLoader。由于二者实现代理的机制不同,所以对延迟加载的支持也不相同。LazyResultLoader只能延迟加载Collection类型的属性,而EnhancedLazyResultLoader可以延迟加载Collection类型的属性,以及自定义类型的属性,而且性能方面要由于LazyResultLoader。
分享到:
评论

相关推荐

    iBATIS实战

    3.3.1 针对延迟加载的字节码增强 48 3.3.2 Jakarta Commons数据库连接池 49 3.3.3 分布式高速缓存 49 3.4 将iBATIS添加到应用程序中 49 3.4.1 在独立应用程序中使用iBATIS 50 3.4.2 在Web应用程序中使用iBATIS 50 ...

    iBatis SQL Maps开发指南.pdf

    延迟加载 VS 联合查询(1:1) 复杂类型集合的属性 避免N+1 Select(1:M和M:N) 组合键值或多个复杂参数属性 支持Parameter Map和Result Map的数据类型 缓存Mapped Statement结果集 只读 VS 可读写 Serializable可...

    ibatis2.x 详细介绍

    延迟加载........................................................................................................ 30 动态映射..............................................................................

    ibatis开发指南中文版

    延迟加载........................................................................................................30 动态映射................................................................................

    ibatis开发指南_夏昕

    延迟加载........................................................................................................30 动态映射................................................................................

    ibatis开发指南

    ibatis的高级特性 数据关联 一对多关系 一对一关系 延迟加载 动态加载 事务管理

    ibatis 开发指南(pdf)

    28 延迟加载........................................................................................................ 30 动态映射...................................................................

    ibatis入门教程

    延迟加载........................................................................................................ 30 动态映射..............................................................................

    iBATIS 帮助文档

    SQL Maps (com.ibatis.sqlmap.*)......................................................................................................5 SQL Map的概念........................................................

    所有j2ee框架方面的原理全集

    对所有j2ee框架的原理做了解析,dwr的实现原理 hibernate缓存的配置 ioc实现原理 javascript原型 javacript中继承 jboss ibatis 解决延迟加载等等本人近段时间的呕心之做

    mybatis_day01.docx

    增加了程序员的一些操作,但是带来了设计上的灵活,并且也是支持hibernate的一些特性,如延迟加载,缓存和映射等;对数据库的兼容性比hibernate差。移植性不好,但是可编写灵活和高性能的sql语句。

    深入浅出Hibernate

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    \深入浅出Hibernate

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    深入浅出Hibernate2

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    《深入浅出Hibernate》1

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    深入浅出Hibernate(PDF)第一部分

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    深入浅出hibernate(PDF)第三部分

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    深入浅出Hibernate(PDF)第二部分

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

    深入浅出Hibernate.pdf

    从一个基础程序入手,讲述Hibernate的基本语法与配置,慢慢升高到缓存、延迟加载等高级特性。本书内容深入浅出,先讲述持久层设计与ORM,再由Hibernate概述、Hibernate基础Hibernate高级特性顺序展开,直至Hibernate...

Global site tag (gtag.js) - Google Analytics