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高级映射及延迟加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现图片合成的示例详解

    Java实现图片合成的示例详解

    前端有一个神器——canvas,这个画布标签可以处理各种图片的合成,可以精确到图片的具体坐标。java后端也有这样的神器,那就是image-combiner,可以很简单的合成图片,感兴趣的可以试一试
    2022-01-01
  • Java中的事件处理机制详解

    Java中的事件处理机制详解

    这篇文章主要介绍了Java中的事件处理机制详解,Java事件处理是采取"委派事件模型",当事件发生时,产生事件的对象,会把此"信息"传递给"事件的监听者"处理,这里所说的"信息"实际上就是java.awt.event事件类库里某个类创建对象,需要的朋友可以参考下
    2023-09-09
  • java多线程教程之如何使用线程池详解

    java多线程教程之如何使用线程池详解

    这篇文章主要给大家介绍了关于java多线程之如何使用线程池的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • Springmvc模式上传和下载与enctype对比

    Springmvc模式上传和下载与enctype对比

    这篇文章主要介绍了Springmvc模式上传和下载与enctype对比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • spring boot + quartz集群搭建的完整步骤

    spring boot + quartz集群搭建的完整步骤

    这篇文章主要给大家介绍了关于spring boot + quartz集群搭建的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-05-05
  • mybatis-plus批处理IService的实现示例

    mybatis-plus批处理IService的实现示例

    这篇文章主要介绍了mybatis-plus批处理IService的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • SpringBoot项目如何添加2FA双因素身份认证

    SpringBoot项目如何添加2FA双因素身份认证

    双因素身份验证2FA是一种安全系统,要求用户提供两种不同的身份验证方式才能访问某个系统或服务,国内普遍做短信验证码这种的用的比较少,不过在国外的网站中使用双因素身份验证的还是很多的,这篇文章主要介绍了SpringBoot项目如何添加2FA双因素身份认证,需要的朋友参考下
    2024-04-04
  • Java毕业设计实战项目之在线服装销售商城系统的实现流程

    Java毕业设计实战项目之在线服装销售商城系统的实现流程

    基础掌握怎么样,用实战检验就知道了,本篇文章手把手带你用java+SpringBoot+Maven+Vue+mysql实现一个在线服装销售商城系统,大家可以在过程中查缺补漏,提升水平
    2022-01-01
  • Java连接MongoDB的常用方法详解

    Java连接MongoDB的常用方法详解

    这篇文章主要为大家详细介绍一下Java语言连接MongoDB的常用方法以及实现增删改查功能的示例代码,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-07-07
  • Java二分查找算法与数组处理的应用实例

    Java二分查找算法与数组处理的应用实例

    二分查找法,又叫做折半查找法,它是一种效率较高的查找方法。数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。Java 语言中提供的数组是用来存储固定大小的同类型元素
    2022-07-07

最新评论