mybatis总概览(6)(延迟加载)

1 延迟加载

1.1 什么是延迟加载

resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能

(即需要时候才执行sql语句或者加载)

需求:

如果查询订单并且关联查询用户信息。如果先查询订单信息即可满足要求,当我们需要查询用户信息时再查询用户信息。把对用户信息的按需去查询就是延迟加载。

延迟加载:

先从单表查询、需要时再从关联表去关联查询,大大提高 数据库性能,因为查询单表要比关联查询多张表速度要快。

1.2 使用association实现延迟加载

1.2.1  需求

查询订单并且关联查询用户信息

1.2.2  mapper.xml

需要定义两个mapper的方法对应的statement。

1、只查询订单信息

SELECT * FROM orders

在查询订单的statement中使用association去延迟加载(执行)下边的satatement(关联查询用户信息)

2、关联查询用户信息

         通过上边查询到的订单信息中user_id去关联查询用户信息

         使用UserMapper.xml中的findUserById

上边先去执行findOrdersUserLazyLoading,当需要去查询用户的时候再去执行findUserById,通过resultMap的定义将延迟加载执行配置起来。

1.2.3  延迟加载resultMap

使用association中的select和column指定延迟加载去执行的statement的sql语句和id。

<!-- 延迟加载的resultMap -->
    <resultMap type="cn.itcast.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap">
            <!--对订单信息进行映射配置  -->
            <id column="id" property="id"/>
            <result column="user_id" property="userId"/>
            <result column="number" property="number"/>
            <result column="createtime" property="createtime"/>
            <result column="note" property="note"/>
            <!-- 实现对用户信息进行延迟加载
            select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement)
            要使用userMapper.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespace
            column:订单信息中关联用户信息查询的列,是user_id
            关联查询的sql理解为:(ps:下面只是子查询,和例子没有太大联系)
            SELECT orders.*,
    (SELECT username FROM USER WHERE orders.user_id = user.id)username,
    (SELECT sex FROM USER WHERE orders.user_id = user.id)sex
     FROM orders
             -->
            <association property="user"  javaType="cn.itcast.mybatis.po.User"
             select="cn.itcast.mybatis.mapper.UserMapper.findUserById" column="user_id">
            <!-- 实现对用户信息进行延迟加载 -->        
            </association>            
    </resultMap>

1.2.4     mapper.java

1.2.5    测试

1.2.5.1 测试思路:

1、执行上边mapper方法(findOrdersUserLazyLoading),
内部去调用cn.itcast.mybatis.mapper.OrdersMapperCustom中的findOrdersUserLazyLoading只查询orders信息(单表)。 2、在程序中去遍历上一步骤查询出的List
<Orders>,当我们调用Orders中的getUser方法时,开始进行延迟加载。 3、延迟加载,去调用UserMapper.xml中findUserbyId这个方法获取用户信息。

1.2.5.2  延迟加载配置

mybatis默认没有开启延迟加载,需要在SqlMapConfig.xml中setting配置。

在mybatis核心配置文件中配置:

lazyLoadingEnabled、aggressiveLazyLoading

aggressiveLazyLoading: 积极懒加载开关, 默认为true, 
这个属性比较搞笑,如果为true则当你访问任何一个属性都会加载所有的其他懒加载属性,即使你根本没有调用哪个懒加载属性,
说白了就是aggressiveLazyLoading=true,则lazy load等于没用,所以要使用lazy load还是将其设为false

(ps:lazyLoadingEnabled、aggressiveLazyLoading的区别

lazyLoadingEnabled:如果是懒加载,会根据映射的配置,调用到具体对象才加载。
aggressiveLazyLoading:如果是积极加载,就算使用到包含懒加载属性的对象,所有懒加载属性会被加载。
总结:确实存在很大重复之处。

在SqlMapConfig.xml中配置:

1.2.5.3              测试代码

特别 注意:

ps:如果测试打印list列表,或者Orders元素对象,会看起来直接获取了,而不是懒加载User对象
(原因:虽然确实是懒加载,但是打印对象会自动调用toString方法(方法的hashcode是通过每个属性得到的),也就是说自动调用其中的User属性

实际应用中,只会先获取Orders对象的其他属性数据,当调用到User属性的时候才会促发懒加载。

1.2.6    延迟加载思考

不使用mybatis提供的association及collection中的延迟加载功能,如何实现延迟加载??

实现方法如下,定义两个mapper方法:
1、查询订单列表
2、根据用户id查询用户信息
实现思路:
先去查询第一个mapper方法,获取订单信息列表
在程序中(service),按需去调用第二个mapper方法去查询用户信息。

总之:

使用延迟加载方法,先去查询简单的sql(最好单表,也可以关联查询(先简单的关联)),再去按需要加载关联查询的其它信息。

 

2,非全局延迟加载

mybatis为我们提供了可以非全局配置的延迟加载功能
在关联的元素(association  ,collection  ,discriminator)中,存在一个属性fetchType来决定是否需要延迟加载
如果配置它,它将覆盖掉原有在MyBatis设置的策略。 对于它而言,它有两个取值: lazy: 延迟加载 eager:即刻加载
<mapper namespace="com.ykzhen2015.csdn.mapper.EmployeeMapper">  
    <resultMap id="employeeMap" type="com.ykzhen2015.csdn.pojo.Employee">  
        <id property="id" column="id" />  
        <result property="empName" column="emp_name" />  
        <result property="sex" column="sex" />  
<association property="employeeCard" column="id" fetchType="lazy" select="com.ykzhen2015.csdn.mapper.EmployeeCardMapper.getEmployeeCardByEmpId" />
<collection property="projectList" column="id" fetchType="eager" select="com.ykzhen2015.csdn.mapper.ProjectMapper.findProjectByEmpId" />
...

 

posted @ 2018-05-09 15:56  假程序猿  阅读(179)  评论(0)    收藏  举报