写点什么

MyBatis 专栏 - 关联查询中的延迟加载

用户头像
小马哥
关注
发布于: 2021 年 02 月 09 日
MyBatis专栏 - 关联查询中的延迟加载

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 */@Datapublic 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 */@Datapublic 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: 11000.0
复制代码


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

==>  Preparing: select * from account where aid=? ==> Parameters: 1(Integer)<==    Columns: aid, money, uid<==        Row: 1, 1000, 1<==      Total: 11000.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: 1User(uid=1, username=Mark1, sex=male, birthday=Tue Jan 01 00:00:00 CST 1985, address=Beijing)
复制代码


发布于: 2021 年 02 月 09 日阅读数: 10
用户头像

小马哥

关注

自强不息,厚德载物 2018.12.22 加入

像一棵竹子那样, 不断的扎根积累, 活出节节高的人生!

评论

发布
暂无评论
MyBatis专栏 - 关联查询中的延迟加载