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

news2025/1/11 21:47:39

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#/.net程序调用python

C#/.net程序调用python C#的优势在于window下的开发&#xff0c;不仅功能强大而且开发周期短。而python则有众多的第三方库&#xff0c;可以避免自己造轮子&#xff0c;利用C#来做界面&#xff0c;而具体实现使用python来实现可以大大提高开发效率。本文介绍如何使用pythonnet…

Kubernetes初始化容器

初始化容器 之前了解了容器的健康检查的两个探针&#xff1a;liveness probe&#xff08;存活探针&#xff09;和readiness probe&#xff08;可读性探针&#xff09;的使用方法&#xff0c;我们说在这两个探针是可以影响容器的生命周期的&#xff0c;包括我们之前提到的容器的…

如何或者无插件Web页面监控播放软件LiveNVR的固定视频流地址,实现大屏上墙、播放、视频分析等目的

1、LiveNVR介绍 LiveNVR的安防监控的视频直播&#xff0c;可以按标准的Onvif/RTSP协议接入监控设备&#xff0c;也可以通过海康、大华、天地伟业等厂家私有SDK接入监控&#xff0c;实现web页面的播放和录像回放。 可以分发HTTP-FLV、WS-FLV、WebRTC、RTMP、HLS(M3U8)、RTSP等多…

Linux安装Tomcat9

默认Linux已经安装了JDK 并且已经配置好了环境变量 下载链接 Tomcat9 下载完成如下图 &#xff0c;这个下载完成需要看一下&#xff0c;有的包里bin目录内缺少bootstrap.jar文件&#xff0c;因此下载包的时候要看看bin目录下的是不是有这个文件&#xff0c;如果没有启动Tomcat…

CHAPTER 1 Linux 集群

集群1 集群介绍2 集群分类1. 高可用性集群&#xff08;High Availability Cluster&#xff09;HA2. 负载均衡集群&#xff08;Load Balance Cluster&#xff09;LB3. 高性能集群&#xff08;High Performance Computing Cluster&#xff09;HPC3 HA集群逻辑架构1. 信息层/基础架…

Qt页面菜单栏、工具栏、状态栏

1、菜单栏 QMenu *editMenu ui->menuBar->addMenu("编辑(&E)");2、编辑菜单栏及工具栏内容 QAction *action_copy editMenu->addAction(QIcon("copy.png"),QString("复制(&c)"));action_copy->setShortcut(QKeySequence(…

数学建模竞赛的一些心得体会

1.数学建模经验首先简要的介绍一下我的情况。数学建模我也是在大一暑假开始接触的&#xff0c;之前对其没有任何的了解。我本身对数学也有相对较厚的兴趣&#xff0c;同时我也是计算机专业的学生&#xff0c;因此&#xff0c;我觉得我可参加数学建模的这个比赛。大一的暑假参加…

Linux->进程终止和等待

目录 1. 进程终止场景 1.1 进程退出码 1.2 进程常见退出方式 2. 进程等待 2.1 进程等待的必要性 2.2 进程等待的方式 wait()方式 waitpid()方式 options参数 status参数 1. 进程终止场景 代码运行完毕&#xff0c;结果正确 代码运行完毕&#xff0c;结果不正确 代码异…

【编程架构实践】关于技术栈和架构

架构是什么&#xff1f;老生常谈了。那就看看ChatGPT怎么说&#xff1a;软件架构是软件工程师在设计一个软件系统时&#xff0c;定义系统架构结构的一种科学方法。它指的是软件系统在软件工程师关注功能、性能和安全等质量属性的条件下&#xff0c;组织系统的方式。换句话说&am…

Flask源码篇:wsgi、Werkzeug与Flask启动工作流程

目录1 wsgi介绍2 使用wsgi实现一个web应用3 Werkzeug介绍4 Flask工作流程分析&#xff08;1&#xff09;创建Flask app&#xff08;2&#xff09;启动Falsk app&#xff08;3&#xff09;分析run_simple方法&#xff08;4&#xff09;分析make_server方法&#xff08;5&#xf…

内容分发网络

介绍 CDN 内容分发网络&#xff08;英语&#xff1a;Content Delivery Network 或 Content Distribution Network&#xff0c;缩写&#xff1a;CDN&#xff09;是建立并覆盖在承载网上&#xff0c;由不同区域的服务器组成的分布式网络。将源站资源缓存到全国各地的边缘服务器&…

【数据库视图】简单学习视图,了解一些视图的简单功能

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#x1f345;&#x1f345;&#x1f345;&#xff0c;今天我想带大家去了解一下数据库的视图,虽然视图这个东西在很多地方(各种公司以及项目)已经不再用了,但是许多大学生在考试的时候涉及,&#x1f6f4;&#x1f6f4;&#x1f…

【c++】STL常用容器5—list容器

文章目录list基本概念list构造函数list赋值和交换list大小操作list插入和删除list数据存取list反转和排序list基本概念 功能&#xff1a;将数据进行链式存储。 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链…

京东物流实时风控实践

摘要&#xff1a;本文整理自京东风控数据产品组架构师周文跃&#xff0c;在 FFA 2022 实时风控专场的分享。本篇内容主要分为六个部分&#xff1a;1. 京东物流业务介绍2. 物流风控场景概括3. 物流风控平台建设4. Flink 赋能5. 技术挑战6. 未来规划Tips&#xff1a;点击「阅读原…

操作系统权限提升(二十)之Linux提权-计划任务提权

系列文章 操作系统权限提升(十八)之Linux提权-内核提权 操作系统权限提升(十九)之Linux提权-SUID提权 计划任务提权 计划任务提权原理 linux计划任务提权是因为权限配置不当&#xff0c;计划任务以root权限运行&#xff0c;低权限的用户可以修改计划任务的文件&#xff0c;…

docker启动容器服务之后访问失败

关于docker启动容器服务之后&#xff0c;宿主机访问失败&#xff08;解决方法&#xff09; 注&#xff1a;在进行docker容器启动宿主机进行容器访问时&#xff0c;无需进行网络的配置&#xff0c;docker容器在启动时会自动解决 第一种原因及修改方法 在进行启动的时候&#…

JVM虚拟机概述(1)

1.JVM概述 1.1为什么要学习JVM 通过学习JVM ( java Virtual Machine )可以帮助我们理解java程序运行的过程&#xff0c;了解虚拟机中各种机制的实现原理。为后期写出优质的代码做好准备&#xff0c;为向更高的层次提升打好基础。 1.2虚拟机 虚拟机的本质就是在windows中&…

深入浅出的学习傅里叶变换

学习傅里叶变换需要面对大量的数学公式&#xff0c;数学功底较差的同学听到傅里叶变换就头疼。事实上&#xff0c;许多数学功底好的数字信号处理专业的同学也不一定理解傅里叶变换的真实含义&#xff0c;不能做到学以致用&#xff01; 事实上&#xff0c;傅里叶变换的相关运算…

敏捷-期末

什么是敏捷开发&#xff1f; 敏捷开发(Agile Development)是一种以人为核心、迭代、循序渐进的开发方法。 怎么理解呢&#xff1f;它不是一门技术&#xff0c;它是一种开发方法&#xff0c;也就是一种软件开发的流程&#xff0c;它会指导我们用规定的环节去一步一步完成项目的开…

阿里云服务器ECS的功能特性有哪些?

本文介绍云服务器ECS的功能特性&#xff0c;帮助您更好地了解和使用云服务器ECS。 1、实例 实例是云上的虚拟计算服务器&#xff0c;内含vCPU、内存、操作系统、网络、磁盘等基础组件。您可以使用阿里云提供的控制台、API等管理工具创建和管理ECS实例&#xff0c;像使用本地服…