联级查询时, 很多情况下只需要单张表的数据, 无需查询所有表, 延时加载实现了这个需求, 减少资源的浪费.
使用说明
MyBatis的延迟加载
- 只能对关联对象进行查询时,使用延迟加载策略。对于主加载对象,均采用直接加载。关联对象以属性的方式添加在主对象中
例如:查询订单表中某个订单信息以及和该订单相关的用户信息:
graph LR
主加载对象:订单对象-->可按需查询的关联对象:用户对象
- 要应用延迟加载查询,只能使用多表单独查询,而不能使用多表连接查询。因为多表连接查询的本质是查询一张表,将多张表首先连接为了一张表后,再进行的查询。查询一个信息,就会将所有信息全部查询到。
根据前文例子构造用于==非延时加载的传统联合查询的SQL语句==如下:
select * from order o left join user u on o.user_id=u.id where o.order_number=201810313239
本语句使用了多表连接查询>左连接查询, 延时加载相关设置对其是无效的, 本语句查询结果是一张组合的表, 不可拆解.
改造上文SQL语句,成为适用延时加载SQL语句:
- mybatis-config.xml开启全局配置
- 添加cglib的依赖(从3.4.1版本开始不用添加)
- 添加resultMap和改造原映射文件中SQL语句
相关的pojo:
public class Order implements Serializable {
private static final long serialVersionUID = 1540810318910L;
//订单id
private Integer id;
//用户id
private Long userId;
//订单号
private String orderNumber;
//用户
private User user;
...set/get等省略...
public class User {
private Long id;
// 用户名
private String userName;
// 密码
private String password;
// 姓名
private String name;
// 年龄
private Integer age;
// 性别,1男性,2女性
private Integer sex;
// 出生日期
private Date birthday;
// 创建时间
private Date created;
// 更新时间
private Date updated;
...set/get等省略...
mybatis-config.xml配置
<!-- 全局配置参数 -->
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 设置按需加载 -->
<!-- mybatis在3.4.1开始默认为false-->
<setting name="aggressiveLazyLoading" value="false" />
</settings>
pom.xml添加依赖(假定是maven过程)
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
修改映射文件(本例不把resultMap抽取为额外映射文件)
<resultMap id="orderUserLazyMap" type="Order" autoMapping="true">
<--
column:查询结果的id字段
property:order对象的id属性
数据库表的主键id映射id, 即使相同也不要省,提高性能
-->
<id column="id" property="id" />
<!--
property:order对象的user属性
javaType:属性名对应的java类型
autoMapping:不写
select:指定延迟加载要执行的statement的id(是根据user_id查询用户信息
的statement,注意:需要前边加namespace
column:订单表中关联用户表的列,是user_id,作为参数传入statement中,
只有一个参数时statement中的#{}原则上可以随意.
如果是多个参数,则需要使用数组,形如:column="{a=user_id,aa=参数2,cc=参数3}",
使用时在statement中的需要哪个参数,如第二个,通过#{aa}/${aa}来使用
-->
<association property="user" javaType="User" select="selectUserById" column="user_id"/>
</resultMap>
<!-- 语句1,查询订单信息 -->
<select id="selectOrderUserLazy" resultMap="orderUserLazyMap">
select * from tb_order where order_number = #{orderNumber}
</select>
<!-- 语句2,查询用户信息 -->
<select id="selectUserById" resultType="User">
select * from tb_user where id = #{id};
</select>
评论区