MyBatis高级映射及延迟加载的实现

 更新时间:2024年11月05日 10:00:34   作者:代码代码快快显灵  
MyBatis在处理对象关系映射时,多对一关系是常见的场景,本文就来介绍了MyBatis高级映射及延迟加载的实现,感兴趣的可以了解一下

多对一:

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

  • 第一种方式:一条SQL语句,级联属性映射。

  • 第二种方式:一条SQL语句,association。

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

怎么区分主表和副表?

原则:谁在前面谁是主表

例如:多对一,多在前面,那么多的那个表就是主表

级联属性映射:

Student类:

package pojo;

/**
 * 学生信息
 * 没有cid这个属性,后期会有特殊的方式来处理这个关系字段
 */
public class Student {
    private Integer sid;
    private String sname;
    private Clazz clazz;

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", clazz=" + clazz +
                '}';
    }

    public Student() {
    }

    public Student(Integer sid, String sname) {
        this.sid = sid;
        this.sname = sname;
    }

    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;
    }
}

对应的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="mapper.StudentMapper">

    <!-- 级联属性映射 -->

    <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_student_plus s
                LEFT JOIN
            t_clazz c ON s.cid = c.cid
        WHERE
            s.sid = #{sid}
    </select>

</mapper>
@Test
    public void testSelectBySid(){
        StudentMapper mapper = SqlSessionUtil.openSession().getMapper(StudentMapper.class);
        Student student = mapper.selectBySid(1);
        System.out.println(student);
    }

sql语句:

2024-10-14 13:29:58.511 [main] DEBUG mapper.StudentMapper.selectById - ==>  Preparing: 
SELECT s.sid, s.sname, c.cid, c.cname FROM t_student_plus s 
LEFT JOIN t_clazz c ON s.cid = c.cid WHERE s.sid = ?

association

对应的sql映射文件:

  <resultMap id="studentResultMapAssociation" type="Student">
        <id property="sid" column="sid"/>
        <result property="sname" column="sname"/>
        <!-- 嵌套映射,将 clazz 对象中的 cid 和 cname 映射 -->
        <association property="clazz" javaType="Clazz">
            <id property="cid" column="cid"/>
            <result property="cname" column="cname"/>
        </association>
    </resultMap>
    <select id="selectByIdAssociation" resultMap="studentResultMap">
        SELECT
            s.sid, s.sname, c.cid, c.cname
        FROM
            t_student_plus s
                LEFT JOIN
            t_clazz c ON s.cid = c.cid
        WHERE
            s.sid = #{sid}
    </select>

association翻译为:关联。 学生对象关联一个班级对象。

关键点说明

  • <resultMap> 元素resultMap 用于映射结果集到 Java 对象。通过定义 StudentResultMap 来描述如何将查询结果映射到 Student 对象。

  • <association> 元素<association> 用于处理多对一的关系映射。它会把 clazz 的数据映射到 Student 对象的 clazz 属性上。

    • property:对应 Student 类中的 clazz 属性。
    • javaType:指定 Clazz 类的全限定名。
    • 通过 property 和 column 进行字段的映射。
  • SQL 查询selectStudentWithClazz 查询使用了 LEFT JOIN 来同时获取 student 和 clazz 的信息,并通过 resultMap 映射到 Student 对象中。

分步查询

  <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <id property="sname" column="sname"/>
       <association property="clazz"
                            select="mapper.ClazzMapper.selectByCid"
                            column="cid"/>
    </resultMap>

<!--两条sql语句,完成多对一的分布查询-->
<!--    这是第一步,根据id值查询学生的所有信息,这些信息当中含有班级id(cid-->
<select id="selectByIdStep1" resultMap="studentResultMapByStep" >
    select sid,sname,cid from t_student_plus where sid = #{sid}
</select>

解释:

  • <resultMap id="studentResultMap" type="Student">:定义了一个结果映射规则,结果将映射到 Student 对象中。
  • <id property="sid" column="sid"/>:将数据库中的 sid 列映射到 Student 类的 sid 属性,通常用于映射主键。
  • <result property="sname" column="sname"/>:将数据库中的 sname 列映射到 Student 类的 sname 属性。
  • <association>:用于描述一个对象属性与其他查询之间的关联。
    • property="clazz":Student 类中对应的属性名是 clazz,它表示学生所属的班级。
    • select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid":指定调用的查询方法,用于获取 Clazz 信息。
    • column="cid":指定当前查询结果中的 cid 列的值,将其作为参数传递给 selectByCid 方法。

 在ClazzMapper接口中添加方法

public interface ClazzMapper {

    /**
     * 分布查询第二步
     * 根据cid获取Clazz信息
     * @param cid
     * @return
     */
    Clazz selectByCid(Integer cid);
}

 ClazzMapper的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="mapper.ClazzMapper">
<select id="selectByCid" resultType="Clazz">
    select cid,cname from t_clazz where cid = #{cid}
</select>
</mapper>

执行结果,可以很明显看到先后有两条sql语句执行:

延迟加载

一对多延迟加载机制和多对一是一样的。同样是通过两种方式:

第一种:fetchType="lazy"

  <resultMap id="studentResultMapByStep" type="Student">
        <id property="sid" column="sid"/>
        <id property="sname" column="sname"/>
       <association property="clazz"
                            select="mapper.ClazzMapper.selectByCid"
                            column="cid"
                            fetchType="lazy"/> <!--添加延迟-->
    </resultMap>

<!--两条sql语句,完成多对一的分布查询-->
<!--    这是第一步,根据id值查询学生的所有信息,这些信息当中含有班级id(cid-->
<select id="selectByIdStep1" resultMap="studentResultMapByStep" >
    select sid,sname,cid from t_student_plus where sid = #{sid}
</select>

第二种:修改全局的配置setting,lazyLoadingEnabled=true,如果开启全局延迟加载,想让某个sql不使用延迟加载:fetchType="eager"

一对多

一对多的实现,通常是在一的一方中有List集合属性。

在Clazz类中添加List<Student> stus; 属性。

package pojo;

import java.util.List;

/**
 * 班级信息
 */
public class Clazz {

    public Clazz() {
    }

    private Integer cid;
    private String cname;
    private List<Student> stus;

    public List<Student> getStus() {
        return stus;
    }

    @Override
    public String toString() {
        return "Clazz{" +
                "cid=" + cid +
                ", cname='" + cname + '\'' +
                ", stus=" + stus +
                '}';
    }

    public void setStus(List<Student> stus) {
        this.stus = stus;
    }

    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;
    }

    public Clazz(Integer cid, String cname) {
        this.cid = cid;
        this.cname = cname;
    }
}

一对多的实现通常包括两种实现方式:

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

collection:

public interface ClazzMapper {

    /**
     * 根据cid获取Clazz信息
     * @param cid
     * @return
     */
    Clazz selectByCid(Integer cid);

    /**
     * 根据班级编号查询班级信息。同时班级中所有的学生信息也要查询。
     * @param cid
     * @return
     */
    Clazz selectClazzAndStusByCid(Integer cid);
}
<resultMap id="clazzResultMap" type="Clazz">
  <id property="cid" column="cid"/>
  <result property="cname" column="cname"/>
  <collection property="stus" ofType="Student">
    <id property="sid" column="sid"/>
    <result property="sname" column="sname"/>
  </collection>
</resultMap>

<select id="selectClazzAndStusByCid" resultMap="clazzResultMap">
  select * from t_clazz c join t_student s on c.cid = s.cid where c.cid = #{cid}
</select>

 注意是ofType,表示“集合中的类型”!!!

分步查询:

<resultMap id="clazzResultMap" type="Clazz">
  <id property="cid" column="cid"/>
  <result property="cname" column="cname"/>
  <!--主要看这里-->
  <collection property="stus"
              select="com.powernode.mybatis.mapper.StudentMapper.selectByCid"
              column="cid"/>
</resultMap>

<!--sql语句也变化了-->
<select id="selectClazzAndStusByCid" resultMap="clazzResultMap">
  select * from t_clazz c where c.cid = #{cid}
</select>
/**
* 根据班级编号获取所有的学生。
* @param cid
* @return
*/
List<Student> selectByCid(Integer cid);
<select id="selectByCid" resultType="Student">
  select * from t_student where cid = #{cid}
</select>

延迟加载

一对多延迟加载机制和多对一是一样的。同样是通过两种方式:

  • 第一种:fetchType="lazy"
  • 第二种:修改全局的配置setting,lazyLoadingEnabled=true,如果开启全局延迟加载,想让某个sql不使用延迟加载:fetchType="eager"

到此这篇关于MyBatis高级映射及延迟加载的实现的文章就介绍到这了,更多相关MyBatis高级映射及延迟加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot中整合Shiro实现权限管理的示例代码

    SpringBoot中整合Shiro实现权限管理的示例代码

    这篇文章主要介绍了SpringBoot中整合Shiro实现权限管理的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • MyBatis的逆向工程详解

    MyBatis的逆向工程详解

    这篇文章主要介绍了MyBatis的逆向工程详解,详细的介绍了逆行工程的概念和实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Java内部类原理、概述与用法实例详解

    Java内部类原理、概述与用法实例详解

    这篇文章主要介绍了Java内部类原理、概述与用法,结合实例形式详细分析了Java内部类的相关概念、原理、访问、调用方法等操作技巧与注意事项,需要的朋友可以参考下
    2019-03-03
  • SpringBoot feign动态设置数据源(https请求)

    SpringBoot feign动态设置数据源(https请求)

    这篇文章主要介绍了SpringBoot如何在运行时feign动态添加数据源,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-08-08
  • Springboot pom项目间接依赖包版本与预期不符原因解决分析

    Springboot pom项目间接依赖包版本与预期不符原因解决分析

    这篇文章主要介绍了Springboot pom项目间接依赖包版本与预期不符原因解决分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • java中关于getProperties方法的使用

    java中关于getProperties方法的使用

    这篇文章主要介绍了java中关于getProperties方法的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • JAVA DOM解析XML文件过程详解

    JAVA DOM解析XML文件过程详解

    这篇文章主要介绍了JAVA DOM解析XML文件过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • SpringCloud网关Gateway功能实现

    SpringCloud网关Gateway功能实现

    本文介绍SpringCloud网关Gateway功能实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09
  • java中的tostring方法的具体用法

    java中的tostring方法的具体用法

    这篇文章主要介绍了java中的tostring方法的具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们来一起学习一下吧
    2019-06-06
  • elasticsearch集群cluster discovery可配式模块示例分析

    elasticsearch集群cluster discovery可配式模块示例分析

    这篇文章主要为大家介绍了elasticsearch集群cluster discovery可配式模块示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04

最新评论