Mybatis | 07 Mybatis延迟加载

Mybatis延迟加载

1. 多表查询的问题

对于多表查询中用户和账户的示例

  1. 在查询用户时,如果把所有关联账户的信息都查询出来会占用较大的内存

  2. 在查询账户时,还要查询所属用户名便于了解账户的详情,单单只有一个用户ID不便于理解

2. 加载方式

2.1 两种加载方式

  • 延迟加载:在真正使用数据时才进行查询,不用的时候不查询(查询用户)

  • 立即加载:不管是否使用,只要调用查询方法就立刻一起进行查询(查询账户)

2.2 两种加载方式的选择

  • 一对多、多对多关系(对多关系):关联的是一个集合会占用较大的内存,通常采用延迟加载

  • 多对一、一对一关系(对一关系):关联的是一个基本对象且包含重要识别信息,通常采用立即加载

2.3 延迟加载的实现

2.3.1 对一关系配置

2.3.1.1 用户DAO接口
public interface IUserDao{
    //根据ID查询用户
    User findUserById(Integer userId);
}
2.3.1.2 账户DAO接口
public interface IAccountDao{
    //查询所有
    List<Account> findAll();
}
2.3.1.3 账户映射文件

使用 association标签 封装实体类对象

标签属性:

  • select属性:指定延迟加载时查询信息使用的方法,值就是使用方法的select标签ID
  • column属性:指定延迟加载时查询方法传入的参数
<!--头文件省略-->
<mapper namespace="org.example.dao.IAccountDao">
	<resultMap id="accountMap" type="account">
    	<id property="id" column="id"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <association property="user" column="uid" javaType="user"
                     select="org.example.dao.IUserDao.findUserById">
        </association>
    </resultMap>
    
    <select id="findAll" resultMap="accountMap">
    	select * from account;
    </select>  
</mapper>

小心别掉坑:注意column属性的值(column属性深入TO Mybatis多表查询篇)

如果ID属性和多表查询中一样使用aid属性列赋值

	<resultMap id="accountMap" type="account">
        <!--使用aid赋值-->
    	<id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <association property="user" column="uid" javaType="user"
                     select="org.example.dao.IUserDao.findUserById">
        </association>
    </resultMap>

由于没有配置别名,ID属性就无法封装,结果就为NULL

出错…

延迟加载_column属性

2.3.1.4 用户映射文件
<!--头文件省略-->
<mapper namespace="org.example.dao.IUserDao">
	<select id="findUserById" parameterType="INT" resultType="user">
    	select * from user where id=#{id};
    </select>
</mapper>

2.3.2 对多关系配置

2.3.2.1 用户DAO接口
public interface IUserDao{
    //查询所有
    List<User> findAll();
}
2.3.2.2 账户DAO接口
public interface IAccountDao{
    //根据用户的ID查询账户
    Account findAccountByUid(Integer userId);
}
2.3.2.3 用户映射文件

使用 collection标签 封装实体类集合

标签属性:

与association标签的属性意义相同

  • select属性:指定延迟加载时查询信息使用的方法,值就是使用方法的select标签ID
  • column属性:指定延迟加载时查询方法传入的参数
<!--头文件省略-->
<mapper namespace="org.example.dao.IUserDao">
	<resultMap id="userMap" type="user">
    	<id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="address" column="address"></result>
        <result property="sex" column="sex"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="accounts" column="id" ofType="account"
                    select="org.example.dao.IAccountDao.findAccountByUid">
        </collection>
    </resultaMap>
    
    <select id="findAll" resultMap="userMap">
    	select * from user;
    </select>
</mapper>
2.3.2.4 账户映射文件
<!--头文件省略-->
<mapper namespace="org.example.dao.IAccountDao">
	<select id="findAccountByUid" parameterType="INT" resultType="account">
    	select * from account where uid=#{uid};
    </select>
</mapper>

2.3.3 开启延迟加载支持

两个与延迟加载有关的全局参数

  • lazyLoadingEnabled

  • aggressiveLazyLoading

主配置文件中开启延迟加载功能

<!--头文件省略-->
<configuration>
	<!--properties标签省略-->
    <settings>
    	<setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
	<!--typeAlises标签配置省略-->
    <!--environments配置省略-->
    <!--mappers配置省略-->
</configuration>

小心别掉坑:注意配置的顺序 (TO Mybatis基本使用篇)

2.3.4 测试代码

以账户查询为例

  • 测试方法
//省略获取session的过程和释放资源过程
@Test
public void findAllAccountTest(){
	List<Account> accounts = accountDao.findAllAccount();
    for(Account account : accounts){
        System.out.println(account);
        System.out.println(account.getUser());
	}
}
  • 测试结果
  1. 未开启延迟加载(立即加载)

延迟加载_一对一开启前

  1. 开启延迟加载仅查询不打印用户信息(不使用用户信息)

延迟加载_使用延迟加载不打印

  1. 开启延迟加载打印用户信息(使用用户信息)

延迟加载_使用延迟加载

Tips 2.1:实现特点

在实现的过程中,都调用了对方的一个方法,实现延迟加载时进行查询

  • 用户延迟查询账户信息时使用了账户接口中根据用户ID查询账户的方法
  • 账户延迟查询用户信息时使用了用户接口中根据用户ID查询用户的方法

以用户查询为例图解

延迟加载_实现特点

Tips 2.2:多表查询关联对象的封装

以账户查询为例

  1. 自己定义封装
  2. 交给关联对象内部封装
  1. 使用多表查询语句,同时使用ID和RESULT标签定义封装方式
<mapper namespace="org.example.dao.IAccount">
	<resultMap id="accountMap" type="account">
    	<id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <association property="user" column="uid" javaType="user">
        	<id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
        </association> 
    </resultMap>
    
    <select id="findAllAccount" resultMap="accountMap">
    	select u.*,a.id as aid,a.uid,a.money from account a,user u 
        where a.uid=u.id;
    </select>
</mapper>
  1. 使用单表查询语句,同时使用SELECT属性调用关联对象的查询方法实现封装
  • 账户映射文件
<mapper namespace="org.example.dao.IAccount">
	<resultMap id="accountMap" type="account">
    	<id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <association property="user" column="uid" javaType="user"
                     select="org.example.dao.IUseDao.findUserById">
        </association> 
    </resultMap>
    
    <select id="findAllAccount" resultMap="accountMap">
    	select * from account;
    </select>
</mapper>
  • 用户映射文件
<mapper namespace="org.example.dao.IUserDao">
	<select id="findUserById" parameterType="INT" resultType="user">
    	select * from user where id=#{id};
    </select>
</mapper>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值