SSM框架系列: (一) Mybatis之延迟加载

延迟加载定义

百度释义: 延迟加载(lazy load)是(也称为懒加载),延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。

理解: Mybatis中, 延迟加载是 对象实体成员属性详情 加载的延迟. 

〇. 前提: 

为说明延迟加载, 先给出如下实体模型, 订单实体 (Order) 中包含基本属性 (id, name, time) 和两个成员属性 (Product实体, Customer实体) ;

一. Mybatis加载方式分为三种, 分别是:

    1. 直接加载: 即使用实体的任何信息时,加载全部信息, 如下图:

    2. 侵入式延迟加载: 即需要使用延迟加载属性详情时, 将该对象的所有延迟加载实体属性一次性加载, 如图:

3. 深度延迟加载: 即真正的按需加载, 只加载真正需要使用的延迟加载项属性, 如图: 

二. 清楚延迟加载的分类后, 来看Mybatis中各种延迟加载策略的配置:

1. 直接加载: 当不进行任何延迟加载配置时, 即为直接加载:

    a. 方式1: 使用select语句一次加载出所有属性, 再使用resultMap进行相应映射 (注解方式使用@Results);

    b. 方式2: 使用select简单查询, 再根据查询结果进行级联查询 (xml方式使用association和collection, 注解方式使用@One和@Many), 该种方式仅查询Order基本属性时, 会立即加载级联加载的属性, log记录如下 (查询基本属性, 导致全部加载): 

2. 侵入式延迟加载: xml配置 (注解方式比较特殊, 请看第4条分讲):

    即在Mybatis核心配置文件中增加设置标签如下, 再使用级联查询, 即实现了侵入式延迟加载:

  <settings>
    <!--打开延迟加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--打开浸入式延迟加载-->
    <setting name="aggressiveLazyLoading" value="true"/>
  </settings>

     但是, 此时若查询两个实体属性中的任意一个时, 会导致另一个实体属性也被加载, 这也是侵入式加载的特点: " 所有延迟加载属性合为一体 ", log下图 (实际未使用3所加载的内容):

3. 深度延迟加载: xml配置 (注解方式比较特殊, 请看第4条分讲):

    即在Mybatis核心配置文件中增加设置标签如下, 再使用级联查询, 即实现了深度延迟加载:

  <settings>
    <!--打开延迟加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--关闭浸入式延迟加载开关, 即进行深度延迟加载-->
    <setting name="aggressiveLazyLoading" value="false"/>
  </settings>

    此时, 但给我们查询Order的其中一个实体成员属性时, 另一个实体成员属性不会被加载, 即实现了深度延迟加载, log日志如下效果: 

4. Myabtis 中的注解配置:  还支持注解配置查询语句, 其中延迟加载的配置时通过在@One或者@ many标签中配置 fetchType = FetchType.LAZY 属性实现, 其作用时替代Mybatis核心配置文件中的懒加载配置, 所以和 2/3 中的注解配置是替换关系, 而不是依赖关系:

配置举例如下:  

    @Select("select * from orders")
    @Results({
            @Result(id = true,property = "id",column = "id"),
            @Result(property = "orderNum",column = "orderNum"),
            @Result(property = "orderTime",column = "orderTime"),
            @Result(property = "peopleCount",column = "peopleCount"),
            @Result(property = "orderDesc",column = "orderDesc"),
            @Result(property = "payType",column = "payType"),
            @Result(property = "orderStatus",column = "orderStatus"),
            @Result(property = "productId",column = "productId"),
            @Result(property = "product",column = "productId",javaType = Product.class,
                    one = @One(select = "com.wen.dao.IProductDao.findProductById",fetchType = FetchType.LAZY)),
            @Result(property = "product2",column = "peopleCount",javaType = Product.class,
                    one = @One(select = "com.wen.dao.IProductDao.findProductById",fetchType = FetchType.LAZY))
    })
    List<Order> findAllOrder();

    此时会有人好奇, 注解方式中并没有侵入式延迟和深度延迟的选项, 经博主实测, Mybatis的注解方式配置延迟加载默认就是 深度延迟加载;

三. 延迟加载策略也的优劣和选择:

    1. 优缺点: 

        优点:
            先查询基本属性, 加快了响应速度, 当需要时才去加载实体成员属性内容
        缺点:
            增加了查询次数, 当大量查询时, 降低了数据库的性能

    2. 选择:

    不使用场景: 深度理解延迟加载的优缺点后, 便可以根据需求进行选择, 当查询数据量大, 且频繁查询成员实体属性时, 使用延迟加载是不合适的, 吃此时会增加数据库的查询次数, 从而导致数据库性能消耗;

    使用场景: 而当查询数据量小, 或者查询时几乎很少但是可能会用到成员实体属性时, 选用延迟加载可以避免多表联查或者大量级联查询, 属于一种数据库代码级别的的性能优化; 

 转载请标明出处: 划船一哥

猜你喜欢

转载自blog.csdn.net/weixin_42711325/article/details/84524536