十二、MyBatis的高级映射及延迟加载

1 数据库表的准备

准备数据库表:一个班级对应多个学生。班级表:t_clazz。学生表:t_stu
在这里插入图片描述
在这里插入图片描述

2 环境搭建

创建模块

打包方式:jar
引入依赖:mybatis依赖、mysql驱动依赖、junit依赖、logback依赖

配置文件:mybatis-config.xml、logback.xml、jdbc.properties
创建工具类:SqlSessionUtil
创建pojo类:Student、Clazz

package com.powernode.mybatis.pojo;

/**
 * 学生信息
 */
public class Student {
    private Integer sid;
    private String sname;
    private Clazz clazz;
	......
	//此处省略构造方法、getting setting toString方法
package com.powernode.mybatis.pojo;

/**
 * 班级信息
 */
public class Clazz {
    private Integer cid;
    private String cname;
    private List<Student> stus;
	......
	//此处省略构造方法、getting setting toString方法

创建mapper接口:StudentMapper、ClazzMapper
创建mapper映射文件:StudentMapper.xml、ClazzMapper.xml

3 多对一

在这里插入图片描述

多种方式,常见的包括三种:

  • 第一种方式:一条SQL语句,级联属性映射。
  • 第二种方式:一条SQL语句,association。
  • 第三种方式:两条SQL语句,分步查询。(这种方式常用:优点一是可复用。优点二是支持懒加载。)

第一种方式:级联属性映射

StudentMapper接口

package com.powernode.mybatis.mapper;

import com.powernode.mybatis.pojo.Student;

public interface StudentMapper {
    /**
     * 根据id获取学生信息,同时获取学生关联的班级信息
     * @param id 学生的id
     * @return 学生对象,但是学生对象里面含有班级对象
     */
    Student selectById(Integer id);
}

StudentMapper.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.powernode.mybatis.mapper.StudentMapper">

    <!--多对一映射的第一种方式:一条SQL语句,级联属性映射-->
    <resultMap id="studentResulMap" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <result property="clazz.cid" column="cid"/>
        <result property="clazz.cname" column="cname"/>
    </resultMap>
    <select id="selectById" resultMap="studentResulMap">
        select
            s.sid,s.sname,c.cid,c.cname
        from
            t_stu s left join t_clazz c on s.cid = c.cid
        where
            s.sid = #{sid}
    </select>
</mapper>

StudentMapperTest

package com.powernode.mybatis.test;

import com.powernode.mybatis.mapper.StudentMapper;
import com.powernode.mybatis.pojo.Student;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class StudentMapperTest {
    @Test
    public void testSelectById(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        Student student = mapper.selectById(1);
        System.out.println(student);
        sqlSession.close();
    }
}

第二种方式:association

association:关联。一个Student对象关联一个Clazz对象
property:提供要映射的POJO类的属性名
javaType:用来指定要映射的java类型

修改resultMap中的配置

 <!--一条SQL语句,association。-->
<resultMap id="studentResulMap" type="Student">
    <id property="sid" column="sid"/>
    <result property="sname" column="sname"/>
    <association property="clazz" javaType="Clazz">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
    </association>
</resultMap>

第三种方式:分步查询

StudentMapper

/**
* 分布查询第一步:先根据学生的sid查询学生的信息
* @param id
* @return
*/
Student selectByIdStep1(Integer id);

StudentMapper.xml

property:pojo类中的属性名称
select:执行的sql语句的id
column:给select传参

<!--第一步:根据学生的id查询学生的所有信息,信息中含有班级的id-->
<resultMap id="studentResulMapByStep" type="Student">
    <id property="sid" column="sid"/>
    <result property="sname" column="sname"/>
    <association property="clazz"
                 select="com.powernode.mybatis.mapper.ClazzMapper.selectByIdStep2"
                 column="cid">
    </association>
</resultMap>
<select id="selectByIdStep1" resultMap="studentResulMapByStep">
    select sid,sname,cid from t_stu where sid = #{sid}
</select>

ClazzMapper

/**
* 分步查询第二步:根据cid获取班级信息
 * @param cid
 * @return
 */
Clazz selectByIdStep2(Integer cid);

ClazzMapper.xml

<mapper namespace="com.powernode.mybatis.mapper.ClazzMapper">
    <!--分步查询第二步-->
    <select id="selectByIdStep2" resultType="Clazz">
        select cid,cname from t_clazz where cid = #{cid}
    </select>
</mapper>

StudentMapperTest

@Test
public void testSelectByIdStep1() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    Student student = mapper.selectByIdStep1(1);
    System.out.println(student);
    sqlSession.close();
}

分步查询的优点:
第一:复用性增强。可以重复利用。(大步拆成N多个小碎步。每一个小碎步更加可以重复利用。)
第二:采用这种分步查询,可以充分利用他们的延迟加载/懒加载机制。

4 延迟加载

什么是延迟加载(懒加载),有什么用

  • 延迟加载的核心原理是:用的时候再执行查询语句。不用的时候不查询。
    作用:提高性能。尽可能的不查,或者说尽可能的少查。来提高效率。

在mybatis当中怎么开启延迟加载

  • 局部设置

    <!--在association中设置的仅是局部设置-->
    <association fetchType="lazy">
    

    注意:默认情况下是没有开启延迟加载的。需要设置:fetchType=“lazy”
    在association标签中配置fetchType=“lazy”,是局部的设置,只对当前的association关联的sql语句起作用。

  • 全局配置
    在mybatis-config.xml核心配置文件中添加全局配置:lazyLoadingEnabled=true

    <settings>
           <!--延迟加载的全局开关,默认值false不开启-->
           <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    

    全局的延迟加载打开。
    如果某一步不需要使用延迟加载, 在association标签中配置fetchType=“eager”

    <association fetchType="eager">
    

5 一对多

一对多:一个班级对应多个学生(班级是主表,学生是副表)
在这里插入图片描述
一对多的实现通常包括两种实现方式:

  • 第一种方式:collection
  • 第二种方式:分步查询

第一种方式:collection

<resultMap id="clazzResultMap" type="Clazz">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
        <!--一对多 collection 集合-->
        <!--ofType 属性用来指定集合中的元素类型-->
        <collection property="stus" ofType="Student">
            <id property="sid" column="sid"/>
            <result property="sname" column="sname"/>
        </collection>
    </resultMap>
    <select id="selectByIdCollection" resultMap="clazzResultMap">
        select c.cid,c.cname,s.sid,s.sname from t_clazz c left join t_stu s on c.cid = s.cid where c.cid = #{cid}
    </select>

第二种方式:分步查询

Clazz selectByStep1(Integer cid);
	<!--分步查询,据班级cid查询班级信息-->
    <resultMap id="selectResultMapStep" type="Clazz">
        <id property="cid" column="cid"/>
        <result property="cname" column="cname"/>
        <collection property="stus"
                    select="com.powernode.mybatis.mapper.StudentMapper.selectByCidStep2"
                    column="cid"/>
    </resultMap>
    <select id="selectByStep1" resultMap="selectResultMapStep">
        select cid,cname from t_clazz where cid = #{cid}
    </select>
List<Student> selectByCidStep2(Integer cid);
<mapper namespace="com.powernode.mybatis.mapper.StudentMapper">
    
    <select id="selectByCidStep2" resultType="Student">
        select * from t_stu where cid = #{cid}
    </select>
</mapper>
@Test
public void testSelectByStep1(){
     SqlSession sqlSession = SqlSessionUtil.openSession();
     ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);
     Clazz clazz = mapper.selectByStep1(1000);
     System.out.println(clazz);
     sqlSession.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值