10- 延迟加载
延迟加载又称为懒加载,按需加载。每次只查询1张表,当需要另一张关联表中的数据的时候,再发送一条SQL语句去查询另一张表中数据。
一对一关联查询使用标签:association
一对多关联查询使用标签:collection
10.1 项目环境
10.1.1 项目目录
10.1.2 SQL数据库语句
-- 1. 查询1号用户的信息
select * from user where id=1;
-- 2. 查询1号用户的扩展信息
select * from user_info where id=1;
10.1.3 用户接口
package cn.guardwhy.dao;
import cn.guardwhy.domain.User;
import cn.guardwhy.domain.UserInfo;
/**
* 持久化接口:UserMapper
*/
public interface UserMapper {
/**
* 通过id查询1个用户
*/
User findUserById(int id);
/**
* 通过id查询1个用户扩展信息
*/
UserInfo findUserInfoById(int id);
}
10.1.4 UserMapper.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="cn.guardwhy.dao.UserMapper">
<!--通过id查询1个用户-->
<select id="findUserById" resultType="User">
select * from user where id = #{id}
</select>
<!--通过id查询一个用户的拓展信息-->
<select id="findUserInfoById" resultType="userInfo">
select * from user_info where id = #{id}
</select>
</mapper>
10.1.5 测试代码
package cn.guardwhy.test;
import cn.guardwhy.dao.UserMapper;
import cn.guardwhy.domain.User;
import cn.guardwhy.domain.UserInfo;
import cn.guardwhy.utils.SessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestUserMapper {
private static SqlSessionFactory factory;
private SqlSession session;
private UserMapper userMapper;
// 创建会话对象,自动提交事务
@Before
public void begin(){
session = SessionFactoryUtils.getSession();
userMapper = session.getMapper(UserMapper.class);
}
@Test
public void testFindUserAndInfo(){
User user = userMapper.findUserById(1);
System.out.println("用户信息:" + user);
UserInfo info = userMapper.findUserInfoById(1);
System.out.println("用户拓展信息:" + info);
}
// 关闭会话
@After
public void end(){
// 手动提交
session.commit();
session.close();
}
}
10.1.6 执行结果
10.2 一对一的延迟加载
10.2.1需求案例
通过id查询1号用户User的基本信息,显示用户名和性别
使用延迟加载的方式,关联查询出对应的用户扩展信息UserInfo,身高和体重。
10.2.2 UserMapper.xml
1) 生成步骤:
- 通过id查询用户扩展信息,查询id为findUserInfoById,指定查询结果为userInfoMap。
- 配置映射id为userAndInfoMap中配置关联映射association,指定property、column和select属性。
- 指定select为上面的findUserInfoById查询,column指定用户主表中的主键id。
- 根据用户id查询用户基本信息,指定查询结果为userAndInfoMap。
association标签的属性 | 说明 |
---|---|
property | 另一方的属性名 |
column | 主表的主键 |
select | 通过主键再去查询的SQL语句 |
<?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="cn.guardwhy.dao.UserMapper">
<!--创建User的映射-->
<resultMap id="userMap" type="user">
<!--映射主键-->
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</resultMap>
<!--创建UserInfo的映射-->
<resultMap id="userInfoMap" type="userInfo">
<!--映射主键-->
<id property="id" column="id"/>
<result property="height" column="height"/>
<result property="weight" column="weight"/>
<result property="married" column="married"/>
</resultMap>
<!--创建一对一的关联extends,将上面的映射关系复制过来-->
<resultMap id="userAndInfoMap" type="user" extends="userMap">
<!--
property:另一方的属性名
column:主表中主键列
select: 查询另一方的SQL语句
-->
<association property="userInfo" column="id" select="findUserInfoById"/>
</resultMap>
<!--通过id查询1个用户-->
<select id="findUserById" resultMap="userAndInfoMap">
select * from user where id = #{id}
</select>
<!--通过id查询一个用户的拓展信息-->
<select id="findUserInfoById" resultMap="userInfoMap">
select * from user_info where id = #{id}
</select>
</mapper>
10.2.3 开启延迟加载
sqlMapConfig.xml中开启延迟加载的settings中的lazyLoadingEnabled
<!--开启延迟加载-->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
10.2.4 测试代码
- 通过id查询用户对象
- 输出用户名和性别的属性
- 查询用户之后,再查询用户扩展信息
@Test
public void testFindUserById(){
User user = userMapper.findUserById(1);
System.out.println("用户名:" + user.getUsername() + ", 性别:" + user.getSex());
// 需要用户的拓展信息
UserInfo userInfo = user.getUserInfo();
System.out.println("身高:" + userInfo.getHeight() + ", 体重:" + userInfo.getWeight());
}
10.2.5 执行结果
10.3 一对多的延迟加载
10.3.1 需求案例
查询1号用户的订单信息。
查询1号用户数据,并且关联查询出这个用户所有的订单数据,使用延迟加载方式实现。
10.3.2 SQL数据表查询
-- 查询1号用户的信息
select * from user where id=1;
-- 查询1号用户的订单信息
select * from order_form where user_id=1;
10.3.3 编写用户接口
/**
* 通过id查询1个用户
*/
User findUserById(int id);
/**
* 通过id查询1个用户扩展信息
*/
UserInfo findUserInfoById(int id);
/**
通过userId查询这个用户所有的订单信息
*/
List<OrderForm> findOrdersByUserId(int userId);
10.3.4 UserMapper.xml
- 保留订单表的映射orderMap
- 增加根据用户id查询订单数据配置
- 修改userAndInfoMap映射,添加collection标签,指定select和column属性
select为findOrdersByUserId。
column为user主表中的主键id
注意:这里与association关联配置到一起了,也可以分开映射。
<?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="cn.guardwhy.dao.UserMapper">
<!--创建User的映射-->
<resultMap id="userMap" type="user">
<!--映射主键-->
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
</resultMap>
<!--创建订单的映射-->
<resultMap id="orderMap" type="orderForm">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="number" column="number"/>
<result property="createTime" column="crate_time"/>
<result property="note" column="note"/>
</resultMap>
<!--创建UserInfo的映射-->
<resultMap id="userInfoMap" type="userInfo">
<!--映射主键-->
<id property="id" column="id"/>
<result property="height" column="height"/>
<result property="weight" column="weight"/>
<result property="married" column="married"/>
</resultMap>
<!--查询某个用户的订单信息-->
<select id="findOrdersByUserId" resultMap="orderMap">
select * from order_form where user_id= #{id};
</select>
<!--创建一对一的关联extends,将上面的映射关系复制过来-->
<resultMap id="userAndInfoMap" type="user" extends="userMap">
<!--
property:另一方的属性名
column:主表中主键列
select: 查询另一方的SQL语句
-->
<association property="userInfo" column="id" select="findUserInfoById"/>
<!--创建一对多的关联-->
<collection property="orders" column="id" select="findOrdersByUserId"/>
</resultMap>
<!--通过id查询1个用户-->
<select id="findUserById" resultMap="userAndInfoMap">
select * from user where id = #{id}
</select>
<!--通过id查询一个用户的拓展信息-->
<select id="findUserInfoById" resultMap="userInfoMap">
select * from user_info where id = #{id}
</select>
</mapper>
10.3.5 测试代码
/**
* 一对多的延迟加载
*/
@Test
public void testFindUserById2(){
User user = userMapper.findUserById(1);
System.out.println("用户名:" + user.getUsername() + ", 性别:" + user.getSex());
// 使用订单信息
List<OrderForm> orders = user.getOrders();
orders.forEach(System.out::println);
}
10.3.6 执行结果