MyBatis专栏8 - 延迟加载

MyBatis 延迟加载

总结: 核心是: 在需要延迟查询的association或者collection中配置select和fetchType属性

​ 前者select配置的是要延迟查询的dao方法

​ 后者fetchType属性配置的是要eager或者lazy加载, 默认是eager

作用: 需要的时候才查询, 减少数据库压力

需求: 查询Account与关联表User, 测试延迟加载User

代码示例

1, 准备两张表

create table user
(
    uid  int primary key auto_increment,
    username varchar(40),
    sex      varchar(10),
    birthday date,
    address  varchar(40)
);

insert into user values (null,'Mark1','male','1999-01-01','Beijing');
insert into user values (null,'Mark2','male','1999-01-01','Beijing');
insert into user values (null,'Mark3','male','1999-01-01','Beijing');
insert into user values (null,'Mark4','male','1999-01-01','Beijing');
insert into user values (null,'Mark5','male','1999-01-01','Beijing');

CREATE TABLE account(
		aid INT PRIMARY KEY auto_increment,
		money DOUBLE,
		uid INT
);
ALTER TABLE account ADD FOREIGN KEY(uid) REFERENCES user(uid);

INSERT INTO `t_account` VALUES (null, '1000', '1');
INSERT INTO `t_account` VALUES (null, '2000', '1');
INSERT INTO `t_account` VALUES (null, '1000', '2');
INSERT INTO `t_account` VALUES (null, '2000', '2');
INSERT INTO `t_account` VALUES (null, '800', '3');


2, 实体Bean

实体Bean: Account

import lombok.Data;

import java.io.Serializable;

/**
 * @Date 2021/2/8
 */
@Data
public class Account implements Serializable {
    private Integer aid;
    private Double money;
    private Integer uid;
    // 关联查询的表
    private User user;
}

实体Bean: User

import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * @Date 2021/2/4
 */
@Data
public class User implements Serializable {

    private int uid;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
}

3, Dao

Dao接口: AccountDao

import com.nengli51.pojo.Account;

public interface AccountDao {
    /**
     * 根据aid查找Account记录
     * @param aid
     * @return
     */
    Account findAccountById(Integer aid);
}

Dao接口: UserDao

import com.nengli51.pojo.User;

import java.util.List;

public interface UserDao {
    /**
     * 根据id查询user记录
     * @param uid
     * @return
     */
    User findUserByUid(int uid);
}

4, Mapper配置文件

Mapper配置文件: AccountDao.xml

延迟加载的配置关键: 在Account的自定义映射关系中, 设置延迟加载的User

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nengli51.dao.AccountDao">
    <cache></cache>
    <!--  自定义映射关系  -->
    <resultMap id="accountUserMap" type="Account">
        <id column="aid" property="aid"></id>
        <result column="money" property="money"></result>
        <result column="uid" property="uid"></result>
      <!--	延迟加载的配置关键
            一对一映射
            select属性表示调用其它的select标签
            column属性表示往要调用的其它的select标签中传入参数
            fetchType="lazy"表示延迟加载(局部配置,只有配置了这个的地方才会延迟加载)
        -->
        <association column="uid" property="user" javaType="User" select="com.nengli51.dao.UserDao.findUserByUid" fetchType="lazy"></association>
    </resultMap>
    <select id="findAccountById" parameterType="int" resultMap="accountUserMap">
        select * from account where aid=#{aid}
    </select>
</mapper>

Mapper配置文件: UserDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nengli51.dao.UserDao">
    <select id="findUserByUid" parameterType="int" resultType="User">
        select * from user where uid=#{uid}
    </select>
</mapper>

5, 测试

分别进行两次测试, 代码一样, 不同之处是修改AccountDao.xml的fetchType配置, 分别测试并查看日志输出

import com.nengli51.dao.AccountDao;
import com.nengli51.pojo.Account;
import com.nengli51.pojo.User;
import com.nengli51.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

/**
 * @Date 2021/2/9
 */
public class TestLazyLoad {
    @Test
    public void testMethod(){
        SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        Account account = accountDao.findAccountById(1);
        System.out.println(account.getMoney());
        //进行延迟加载的时候开启之后, 才会发送对关联表的查询
        //User user = account.getUser();
        //System.out.println(user);
        MyBatisUtils.commitAndClose(sqlSession);
    }
}

fetchType="lazy"的测试结果, 即, 开启了延迟加载的情况, 可以看到进行了一次SQL查询.(打开上面代码的注释, 才会发送第二条SQL)

==>  Preparing: select * from account where aid=? 
==> Parameters: 1(Integer)
<==    Columns: aid, money, uid
<==        Row: 1, 1000, 1
<==      Total: 1
1000.0

fetchType="eager"的测试结果, 可以看到进行了两次SQL查询(关掉代码的注释, 但是依然会自动发送对关联表的查询)

==>  Preparing: select * from account where aid=? 
==> Parameters: 1(Integer)
<==    Columns: aid, money, uid
<==        Row: 1, 1000, 1
<==      Total: 1
1000.0
==>  Preparing: select * from user where uid=? 
==> Parameters: 1(Integer)
<==    Columns: uid, username, sex, birthday, address
<==        Row: 1, Mark1, male, 1985-01-01, Beijing
<==      Total: 1
User(uid=1, username=Mark1, sex=male, birthday=Tue Jan 01 00:00:00 CST 1985, address=Beijing)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

能力工场小马哥

如果对您有帮助, 请打赏支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值