当前位置: 首页 > 图灵资讯 > 技术篇> mybatis的高级映射即延迟加载

mybatis的高级映射即延迟加载

来源:图灵教育
时间:2023-06-08 09:23:05

打包⽅式:jar

依赖:mybatis依赖,mysql驱动依赖,junit依赖,logback依赖

配置⽂件:mybatis-config.xml、logback.xml、jdbc.properties

拷⻉⼯具类:SqlSessionUtil

1.准备数据1031.1创建数据库1033

⼀一个班对应多个学习⽣。班级表:t_clazz。学⽣表:t_student

mybatis的高级映射即延迟加载_延迟加载

mybatis的高级映射即延迟加载_ci_02

1.2创建pojo:Student、Clazz104
package com.powernode.mybatis.pojo;//实体类 学生 pojo  104/** * 学生信息 */public class Student { // Student是多方    private Integer sid;    private String sname;    private Clazz clazz; // Clazz是一方。    @Override    public String toString() {        return "Student{" +                "sid=" + sid +                ", sname='" + sname + '\'' +                ", clazz=" + clazz +                '}';    }    public Clazz getClazz() {        return clazz;    }    public void setClazz(Clazz clazz) {        this.clazz = clazz;    }    public Integer getSid() {        return sid;    }    public void setSid(Integer sid) {        this.sid = sid;    }    public String getSname() {        return sname;    }    public void setSname(String sname) {        this.sname = sname;    }    public Student(Integer sid, String sname) {        this.sid = sid;        this.sname = sname;    }    public Student() {    }}
package com.powernode.mybatis.pojo;//实体类 班级 pojo  104import java.util.List;/** * 班级信息 */public class Clazz {    private Integer cid;    private String cname;    public Clazz() {    }    public Clazz(Integer cid, String cname) {        this.cid = cid;        this.cname = cname;    }    public Integer getCid() {        return cid;    }    public void setCid(Integer cid) {        this.cid = cid;    }    public String getCname() {        return cname;    }    public void setCname(String cname) {        this.cname = cname;    }    @Override    public String toString() {        return "Clazz{" +                "cid=" + cid +                ", cname='" + cname + '\'' +                '}';    }}
2.多对一映射实体关系105

多对一:

多一方是:Student

一、方是:Clazz

2.1如何分为主表和副表?105

原则:谁在前,谁是主表。

多对一:多在前,那么多就是主表。

一对多:一-在前,那么一-就是主表。

mybatis的高级映射即延迟加载_System_03

2.2多种⽅式,常⻅包括三种:106

●第⼀种⽅式:⼀条SQL语句,级联属性映射。

●第⼆种⽅式:⼀条SQL语句,association。

●第三种⽅类型:两个SQL语句,分步查询。(这种。⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加载。)

2.2.1第⼀种⽅式:⼀SQL语句,级联属性映射。106

添加pojo类Student⼀个属性:Clazzclazz;表示学⽣相关班级对象。

@Test    public void testselectById(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectById(1);        System.out.println(student.getSid());        System.out.println(student.getSname());        System.out.println(student.getClazz().getCid());        System.out.println(student.getClazz().getCname());                //System.out.println(student);        sqlSession.close();    }

 

<!--这个标签的作用是指定学生表t_stu和Java pojo Student的对应关系    多对一映射的第一种方式:SQL语句,级联属性映射。-->    <resultMap id="studentResultMap" 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="studentResultMap">        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>

 

mybatis的高级映射即延迟加载_sql_04

2.2.2第⼆种⽅式:⼀条SQL语句,association。107

association:翻译为关联。Student对象与Clazz对象相关联。

property:提供要映射的POJO类属性名。

javaType:用于指定要映射的java类型。

 <!--SQL语句,association。  107-->    <resultMap id="studentResultMapAssociation" type="Student">        <id property="sid" column="sid"/>        <result property="sname" column="sname"/>        <!--            association:翻译是相关的。--            association:翻译为关联。Student对象与Clazz对象相关联。                property:提供要映射的POJO类属性名。                javaType:用于指定要映射的java类型。        -->        <association property="clazz" javaType="Clazz">            <id property="cid" column="cid"/>            <result property="cname" column="cname"/>        </association>    </resultMap>    <select id="selectByIdAssociation" resultMap="studentResultMapAssociation">        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>
//第二种方式 SQL语句,association  107    @Test    public void testSelectByIdAssociation(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectByIdAssociation(4);        System.out.println(student);        sqlSession.close();    }

mybatis的高级映射即延迟加载_sql_05

2.2.3第三种⽅类型:两个SQL语句,分步查询。108

(这种⽅式常⽤:优点⼀是可复⽤。优点⼆是⽀持懒加载。)

2.2.3.1第一步:108

根据学生的身份证查询学生的所有信息。这些信息包含班级身份证(cid)

StudentMapper

/**     * 这是多对一     * 分部查询第一步:先根据学生的sid查询学生的信息。  108     * @param sid     * @return     */    Student selectbyidstep1(Integer sid);

com.powernode.mybatis.test

StudentMapperTest

//分部查询第一步:先根据学生的sid查询学生的信息。  108    //分步查询第二步:根据cid获取班级信息。  108    @Test    public void testelectbyidstep1(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectbyIdstep1(5);        //System.out.println(student);        // 懒加载 只要看学生的名字  109        System.out.println(student.getSname());        // 程序执行到此为止,我想看看班级的名字        //System.out.println(student.getClazz().getCname());        sqlSession.close();    }
2.2.3.2第⼆步:108

com.powernode.mybatis.mapper

在Clazmapper中⼝中添加⽅法

/**     * 这是多对一     * 步骤2:根据cid获取班级信息。  108     * @param cid     * @return     */    Clazz selectbyidstep2(Integer cid);

clazmapper.xml⽂件中进⾏配置

<!--步骤2:根据cid获取班级信息。  108-->    <select id=“selectbyIdstep2” resultType="Clazz">        select cid,cname from t_clazz where cid = #{cid}    </select>

mybatis的高级映射即延迟加载_延迟加载_06

3.多对⼀延迟加载1093.1分步查询的优点:109

一是复用性增强。可重复使用。(大步拆成N多个小步骤。每一个小步骤都可以重复使用。)

第二:采用这种分步查询,可以充分利用其延迟加载/懒惰加载机制。

3.2什么是延迟加载(懒加载)?有什么用?109

延迟加载的核心原理是:使用时执行查询句。不使用时不查询。

功能:提高性能。尽量不检查,或尽量少检查。提高效率。

3.2.如何在mybatis中打开延迟加载?109

在association标签中添加fetchtype=lazy"

注:默认情况下未打开延迟加载。需要设置:fetchType="lazy"

在association标签中配置fetchtype=lazy“,是局部设置,只对当前association相关的sql语句起作用。

3.2.1.1延迟加载的全局开关109

在实际开发中,大多数都需要使用延迟加载,因此建议启动所有延迟加载机制:

将全局配置添加到mybatis核心配置文件中:lazyLoadingEnabled=true

<settings>        <!--全局开关延迟加载。不打开默认值false。  109-->        <!--什么意思:只要有分步,都是延迟加载。-->        <setting name="lazyLoadingEnabled" value="true"/>    </settings>

实际开发中的模式:

打开全局延迟加载。

若某一步不需要延迟加载,请设置:fetchType="eager"

3.2.2例109

要想⽀延迟加载,⾮通常很简单,只需在association标签中添加fetchtype=“lazy"即可。

修改Studentmapper.xml⽂件

我们现在只查询学习⽣修改测试程序:

<resultMap id="studentResultMapByStep" type="Student">        <id property="sid" column="sid"/>        <result property="sname" column="sname"/>        <association property="clazz"                     select="com.powernode.mybatis.mapper.ClazzMapper.selectbyIdstep2                     column="cid"                     fetchType="lazy"/>    </resultMap>    <select id=selectbyIdstep1 resultMap="studentResultMapByStep">        select sid,sname,cid from t_stu where sid = #{sid}    </select>
@Test    public void testelectbyidstep1(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectbyIdstep1(5);        //System.out.println(student);        // 懒加载 只要看学生的名字  109        System.out.println(student.getSname());        // 程序执行到此为止,我想看看班级的名字  109        //System.out.println(student.getClazz().getCname());        sqlSession.close();    }

mybatis的高级映射即延迟加载_ci_07

假如后续需要使用⽤到学⽣班级名称,此时将执行⾏修改相关SQL语句的测试程序:

@Test    public void testelectbyidstep1(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectbyIdstep1(5);        //System.out.println(student);        // 懒加载 只要看学生的名字  109        System.out.println(student.getSname());        // 程序执行到此为止,我想看看班级的名字  109        System.out.println(student.getClazz().getCname());        sqlSession.close();    }

mybatis的高级映射即延迟加载_System_08

通过以上执行⾏只有当使才能看到结果。⽤到了班名之后,才会执行⾏相关的sql语句,即延迟加载

4.一对多110

mybatis的高级映射即延迟加载_延迟加载_09

4.1⼀对多的实现通常包括两种实现⽅式:1114.1.1第⼀种⽅式:collection

注意oftype,表示“集合类型”。

ClazzMapper.xml

<resultMap id="clazzResultMap" type="Clazz">        <id property="cid" column="cid"/>        <result property="cname" column="cname"/>        <!--一对多,这里是collection。--一对多,这里是collection。collection是集合的意思。111-->        <!--ofType 该属性用于指定集合中的元素类型。-->        <collection property="stus" ofType="Student">            <id property="sid" column="sid"/>            <result property="sname" column="sname"/>        </collection>    </resultMap>    <select id="selectByCollection" 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>

ClazzMapperTest

//根据班级编号查询班级信息。   111    @Test    public void testSelectByCollection(){        SqlSession sqlSession = SqlSessionUtil.openSession();        ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);        Clazz clazz = mapper.selectByCollection(1000);        System.out.println(clazz);        sqlSession.close();    }

mybatis的高级映射即延迟加载_sql_10

4.1.2第⼆种⽅类型:分步查询112

第一步

ClazzMapper

/**     * 这是一对多     * 分步查询。第一步:根据班级编号获取班级信息。   112     * @param cid 班级编号     * @return     */    Clazz selectBystep1(Integer cid);

ClazzMapper.xml

<!--步骤1:根据班级cid获取班级信息。  112-->    <resultMap id="clazzResultMapStep" type="Clazz">        <id property="cid" column="cid"/>        <result property="cname" column="cname"/>        <collection property="stus"                    select="com.powernode.mybatis.mapper.StudentMapper.selectByCidstep2                    column="cid" fetchType="eager" />    </resultMap>    <select id=selectbystep1 resultMap="clazzResultMapStep">        select cid,cname from t_clazz where cid = #{cid}    </select>

ClazzMapperTest

//分步查询。第一步:根据班级编号获取班级信息。   112    @Test    public void testselectbystep1(){        SqlSession sqlSession = SqlSessionUtil.openSession();        ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);        Clazz clazz = mapper.selectBystep1(1000);        //System.out.println(clazz);        // 只访问班级名称。        System.out.println(clazz.getCname());        // 只有在使用时才会执行第二步SQL        //System.out.println(clazz.getStus());        sqlSession.close();    }

第二步

StudentMapper

/**     * 这是一对多     * 第二步是分布查询     * 根据班级编号查询学生信息。  112     * @param cid     * @return     */    List<Student> selectByCidstep2(Integer cid);

StudentMapper.xml

<select id=selectbyCidstep2 resultType="Student">        select * from t_stu where cid = #{cid}    </select>

mybatis的高级映射即延迟加载_sql_11

5.代码汇总main中com.powernode.mybatis.mapperClazzMapper
package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Clazz;///班级接口  104public interface ClazzMapper {    /**     * 这是一对多     * 分步查询。第一步:根据班级编号获取班级信息。   112     * @param cid 班级编号     * @return     */    Clazz selectBystep1(Integer cid);    /**     * 根据班级编号查询班级信息。   111     * @param cid     * @return     */    Clazz selectByCollection(Integer cid);    /**     * 这是多对一     * 步骤2:根据cid获取班级信息。  108     * @param cid     * @return     */    Clazz selectbyidstep2(Integer cid);}
StudentMapper
package com.powernode.mybatis.mapper;import com.powernode.mybatis.pojo.Student;import java.util.List;///学生接口  104public interface StudentMapper {    /**     * 这是一对多     * 第二步是分布查询     * 根据班级编号查询学生信息。  112     * @param cid     * @return     */    List<Student> selectByCidstep2(Integer cid);    /**     * 这是多对一     * 分部查询第一步:先根据学生的sid查询学生的信息。  108     * @param sid     * @return     */    Student selectbyidstep1(Integer sid);    /**     * SQL语句,association  107     * @param id     * @return     */    Student selectByIdAssociation(Integer id);    /**     * 第⼀种⽅式:⼀条SQL语句,级联属性映射。   106     * 根据id获取学生信息。   106     * 根据id获取学生信息。同时获取与学生相关的课堂信息。  106     * @param id 学生的id     * @return 学生对象,但学生对象包含班级对象。     */    Student selectById(Integer id);}
ClazzMapper.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.ClazzMapper">    <!--这是一对多 步骤1:根据班级cid获取班级信息。  112-->    <resultMap id="clazzResultMapStep" type="Clazz">        <id property="cid" column="cid"/>        <result property="cname" column="cname"/>        <collection property="stus"                    select="com.powernode.mybatis.mapper.StudentMapper.selectByCidstep2                    column="cid" fetchType="eager" />    </resultMap>    <select id=selectbystep1 resultMap="clazzResultMapStep">        select cid,cname from t_clazz where cid = #{cid}    </select>    <resultMap id="clazzResultMap" type="Clazz">        <id property="cid" column="cid"/>        <result property="cname" column="cname"/>        <!--一对多,这里是collection。--一对多,这里是collection。collection是集合的意思。111-->        <!--ofType 该属性用于指定集合中的元素类型。-->        <collection property="stus" ofType="Student">            <id property="sid" column="sid"/>            <result property="sname" column="sname"/>        </collection>    </resultMap>    <select id="selectByCollection" 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>    <!--这是多对一步查询的第二步:根据cid获取班级信息。  108-->    <select id=“selectbyIdstep2” resultType="Clazz">        select cid,cname from t_clazz where cid = #{cid}    </select></mapper>
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">    <!--这是一对多 步骤2:根据班级编号查询学生信息。--这是一对多 步骤2:根据班级编号查询学生信息。  108-->    <select id=selectbyCidstep2 resultType="Student">        select * from t_stu where cid = #{cid}    </select>    <!--        分步查询的优点:            一是增强复用性。可重复使用。(大步拆成N多个小步。每一个小步骤都可以重复使用。)            第二:采用这种分步查询,可以充分利用其延迟加载/懒惰加载机制。        什么是延迟加载(懒加载),有什么用?            延迟加载的核心原理是在使用时执行查询句。不用的时候不查询。            功能:提高性能。尽量不查,或者尽量少查。提高效率。        如何在mybatis中打开延迟加载?            在association标签中添加fetchtype=lazy"            注:默认情况下未打开延迟加载。需要设置:fetchType="lazy"            在association标签中配置fetchtype=lazy“,是局部设置,只对当前association相关的sql语句起作用。        在实际开发中,大多数都需要使用延迟加载,因此建议启动所有延迟加载机制:            将全局配置添加到mybatis核心配置文件中:lazyLoadingEnabled=true        实际开发中的模式:            打开全局延迟加载。            若某一步不需要延迟加载,请设置:fetchType="eager"    -->    <!--两个SQL语句,完成多对一步骤查询。-->    <!--多对一是第一步:根据学生的身份证查询学生的所有信息。这些信息包含班级id(cid)-->    <!--这个association中的select需要指定另一个sql语句的id-->    <resultMap id="studentResultMapByStep" type="Student">        <id property="sid" column="sid"/>        <result property="sname" column="sname"/>        <association property="clazz"                     select="com.powernode.mybatis.mapper.ClazzMapper.selectbyIdstep2                     column="cid"                     fetchType="eager"/>    </resultMap>    <select id=selectbyIdstep1 resultMap="studentResultMapByStep">        select sid,sname,cid from t_stu where sid = #{sid}    </select>    <!--SQL语句,association。  107-->    <resultMap id="studentResultMapAssociation" type="Student">        <id property="sid" column="sid"/>        <result property="sname" column="sname"/>        <!--            association:翻译是相关的。--            association:翻译为关联。Student对象与Clazz对象相关联。                property:提供要映射的POJO类属性名。                javaType:用于指定要映射的java类型。        -->        <association property="clazz" javaType="Clazz">            <id property="cid" column="cid"/>            <result property="cname" column="cname"/>        </association>    </resultMap>    <select id="selectByIdAssociation" resultMap="studentResultMapAssociation">        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>    <!--这个标签的作用是指定学生表t_stu和Java pojo Student的对应关系  106    多对一映射的第一种方式:SQL语句,级联属性映射。-->    <resultMap id="studentResultMap" 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="studentResultMap">        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>
test中com.powernode.mybatis.testClazzMapperTest
package com.powernode.mybatis.test;import com.powernode.mybatis.mapper.ClazzMapper;import com.powernode.mybatis.pojo.Clazz;import com.powernode.mybatis.utils.SqlSessionUtil;import org.apache.ibatis.session.SqlSession;import org.junit.Test;public class ClazzMapperTest {    //分步查询。第一步:根据班级编号获取班级信息。   112    @Test    public void testselectbystep1(){        SqlSession sqlSession = SqlSessionUtil.openSession();        ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);        Clazz clazz = mapper.selectBystep1(1000);        //System.out.println(clazz);        // 只访问班级名称。        System.out.println(clazz.getCname());        // 只有在使用时才会执行第二步SQL        //System.out.println(clazz.getStus());        sqlSession.close();    }    //根据班级编号查询班级信息。   111    @Test    public void testSelectByCollection(){        SqlSession sqlSession = SqlSessionUtil.openSession();        ClazzMapper mapper = sqlSession.getMapper(ClazzMapper.class);        Clazz clazz = mapper.selectByCollection(1000);        System.out.println(clazz);        sqlSession.close();    }}
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 {    //分部查询第一步:先根据学生的sid查询学生的信息。  108    //分步查询第二步:根据cid获取班级信息。  108    @Test    public void testelectbyidstep1(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectbyIdstep1(5);        //System.out.println(student);        // 懒加载 只要看学生的名字  109        System.out.println(student.getSname());        // 程序执行到此为止,我想看看班级的名字  109        System.out.println(student.getClazz().getCname());        sqlSession.close();    }    //第二种方式 SQL语句,association  107    @Test    public void testSelectByIdAssociation(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectByIdAssociation(4);        System.out.println(student);        sqlSession.close();    }    //第⼀种⽅式:⼀条SQL语句,级联属性映射。    ///根据id获取学生信息。    ///根据id获取学生信息。同时获取与学生相关的班级信息。  106    @Test    public void testselectById(){        SqlSession sqlSession = SqlSessionUtil.openSession();        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);        Student student = mapper.selectById(1);        System.out.println(student.getSid());        System.out.println(student.getSname());        System.out.println(student.getClazz().getCid());        System.out.println(student.getClazz().getCname());        System.out.println(student);        sqlSession.close();    }}
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <properties resource="jdbc.properties"/>    <settings>        <!--全局开关延迟加载。--全局开关延迟加载。false不打开默认值。  109-->        <!--什么意思:只要有分步,都是延迟加载。-->        <setting name="lazyLoadingEnabled" value="true"/>    </settings>        <typeAliases>        <package name="com.powernode.mybatis.pojo"/>    </typeAliases>    <environments default="dev">        <environment id="dev">            <transactionManager type="JDBC"/>            <dataSource type="POOLED">                <property name="driver" value="${jdbc.driver}"/>                <property name="url" value="${jdbc.url}"/>                <property name="username" value="${jdbc.username}"/>                <property name="password" value="${jdbc.password}"/>            </dataSource>        </environment>    </environments>    <mappers>        <package name="com.powernode.mybatis.mapper"/>    </mappers></configuration>

剩余的

pojo

utils

logback.xml

jdbc.properties

pom.xml

不做赘述