SSM - Springboot - MyBatis-Plus 全栈体系(十六)

news2024/11/26 4:21:38

第三章 MyBatis

三、MyBatis 多表映射

2. 对一映射

2.1 需求说明
  • 根据 ID 查询订单,以及订单关联的用户的信息!
2.2 OrderMapper 接口
public interface OrderMapper {
  Order selectOrderWithCustomer(Integer orderId);
}
2.3 OrderMapper.xml 配置文件
<!-- 创建resultMap实现“对一”关联关系映射 -->
<!-- id属性:通常设置为这个resultMap所服务的那条SQL语句的id加上“ResultMap” -->
<!-- type属性:要设置为这个resultMap所服务的那条SQL语句最终要返回的类型 -->
<resultMap id="selectOrderWithCustomerResultMap" type="order">

  <!-- 先设置Order自身属性和字段的对应关系 -->
  <id column="order_id" property="orderId"/>

  <result column="order_name" property="orderName"/>

  <!-- 使用association标签配置“对一”关联关系 -->
  <!-- property属性:在Order类中对一的一端进行引用时使用的属性名 -->
  <!-- javaType属性:一的一端类的全类名 -->
  <association property="customer" javaType="customer">

    <!-- 配置Customer类的属性和字段名之间的对应关系 -->
    <id column="customer_id" property="customerId"/>
    <result column="customer_name" property="customerName"/>

  </association>

</resultMap>

<!-- Order selectOrderWithCustomer(Integer orderId); -->
<select id="selectOrderWithCustomer" resultMap="selectOrderWithCustomerResultMap">

  SELECT order_id,order_name,c.customer_id,customer_name
  FROM t_order o
  LEFT JOIN t_customer c
  ON o.customer_id=c.customer_id
  WHERE o.order_id=#{orderId}

</select>
  • 对应关系可以参考下图:

在这里插入图片描述

2.4 Mybatis 全局注册 Mapper 文件
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>

  <!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>

</mappers>
2.5 junit 测试程序
@Slf4j
public class MyBatisTest {

    private SqlSession session;
    // junit会在每一个@Test方法前执行@BeforeEach方法

    @BeforeEach
    public void init() throws IOException {
        session = new SqlSessionFactoryBuilder()
                .build(
                        Resources.getResourceAsStream("mybatis-config.xml"))
                .openSession();
    }

    @Test
    public void testRelationshipToOne() {

      OrderMapper orderMapper = session.getMapper(OrderMapper.class);
      // 查询Order对象,检查是否同时查询了关联的Customer对象
      Order order = orderMapper.selectOrderWithCustomer(2);
      log.info("order = " + order);

    }

    // junit会在每一个@Test方法后执行@@AfterEach方法
    @AfterEach
    public void clear() {
        session.commit();
        session.close();
    }
}
2.6 关键词
  • 在“对一”关联关系中,我们的配置比较多,但是关键词就只有:associationjavaType

3. 对多映射

3.1 需求说明
  • 查询客户和客户关联的订单信息!
3.2 CustomerMapper 接口
public interface CustomerMapper {

  Customer selectCustomerWithOrderList(Integer customerId);

}
3.3 CustomerMapper.xml 文件
<!-- 配置resultMap实现从CustomerOrderList的“对多”关联关系 -->
<resultMap id="selectCustomerWithOrderListResultMap"

  type="customer">

  <!-- 映射Customer本身的属性 -->
  <id column="customer_id" property="customerId"/>

  <result column="customer_name" property="customerName"/>

  <!-- collection标签:映射“对多”的关联关系 -->
  <!-- property属性:在Customer类中,关联“多”的一端的属性名 -->
  <!-- ofType属性:集合属性中元素的类型 -->
  <collection property="orderList" ofType="order">

    <!-- 映射Order的属性 -->
    <id column="order_id" property="orderId"/>

    <result column="order_name" property="orderName"/>

  </collection>

</resultMap>

<!-- Customer selectCustomerWithOrderList(Integer customerId); -->
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
  SELECT c.customer_id,c.customer_name,o.order_id,o.order_name
  FROM t_customer c
  LEFT JOIN t_order o
  ON c.customer_id=o.customer_id
  WHERE c.customer_id=#{customerId}
</select>
  • 对应关系可以参考下图:

在这里插入图片描述

3.4 Mybatis 全局注册 Mapper 文件
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
  <!-- 在mapper标签的resource属性中指定Mapper配置文件以“类路径根目录”为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>
  <mapper resource="mappers/CustomerMapper.xml"/>
</mappers>
3.5 junit 测试程序
@Test
public void testRelationshipToMulti() {

  CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
  // 查询Customer对象同时将关联的Order集合查询出来
  Customer customer = customerMapper.selectCustomerWithOrderList(1);
  log.info("customer.getCustomerId() = " + customer.getCustomerId());
  log.info("customer.getCustomerName() = " + customer.getCustomerName());
  List<Order> orderList = customer.getOrderList();
  for (Order order : orderList) {
    log.info("order = " + order);
  }
}
3.6 关键词
  • 在“对多”关联关系中,同样有很多配置,但是提炼出来最关键的就是:“collection”和“ofType”

4. 多表映射总结

4.1 多表映射优化
setting 属性属性含义可选值默认值
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。NONE, PARTIAL, FULLPARTIAL
  • 我们可以将 autoMappingBehavior 设置为 full,进行多表 resultMap 映射的时候,可以省略符合列和属性命名映射规则(列名=属性名,或者开启驼峰映射也可以自定映射)的 result 标签!

  • 修改 mybatis-sconfig.xml:

<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>
  • 修改 teacherMapper.xml
<resultMap id="teacherMap" type="teacher">
    <id property="tId" column="t_id" />
    <!-- 开启自动映射,并且开启驼峰式支持!可以省略 result!-->
<!--        <result property="tName" column="t_name" />-->
    <collection property="students" ofType="student" >
        <id property="sId" column="s_id" />
<!--            <result property="sName" column="s_name" />-->
    </collection>
</resultMap>
4.2 多表映射总结
关联关系配置项关键词所在配置文件和具体位置
对一association 标签/javaType 属性/property 属性Mapper 配置文件中的 resultMap 标签内
对多collection 标签/ofType 属性/property 属性Mapper 配置文件中的 resultMap 标签内

四、MyBatis 动态语句

1. 动态语句需求和简介

  • 经常遇到很多按照很多查询条件进行查询的情况,比如智联招聘的职位搜索等。其中经常出现很多条件不取值的情况,在后台应该如何完成最终的 SQL 语句呢?

在这里插入图片描述

  • 动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
  • 使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
  • 如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

2. if 和 where 标签

  • 使用动态 SQL 最常见情景是根据条件包含 where / if 子句的一部分。比如:
<!-- List<Employee> selectEmployeeByCondition(Employee employee); -->
<select id="selectEmployeeByCondition" resultType="employee">
    select emp_id,emp_name,emp_salary from t_emp
    <!-- where标签会自动去掉“标签体内前面多余的and/or” -->
    <where>
        <!-- 使用if标签,让我们可以有选择的加入SQL语句的片段。这个SQL语句片段是否要加入整个SQL语句,就看if标签判断的结果是否为true -->
        <!-- 在if标签的test属性中,可以访问实体类的属性,不可以访问数据库表的字段 -->
        <if test="empName != null">
            <!-- 在if标签内部,需要访问接口的参数时还是正常写#{} -->
            or emp_name=#{empName}
        </if>
        <if test="empSalary &gt; 2000">
            or emp_salary>#{empSalary}
        </if>
        <!--
         第一种情况:所有条件都满足 WHERE emp_name=? or emp_salary>?
         第二种情况:部分条件满足 WHERE emp_salary>?
         第三种情况:所有条件都不满足 没有where子句
         -->
    </where>
</select>

3. set 标签

<!-- void updateEmployeeDynamic(Employee employee) -->
<update id="updateEmployeeDynamic">
    update t_emp
    <!-- set emp_name=#{empName},emp_salary=#{empSalary} -->
    <!-- 使用set标签动态管理set子句,并且动态去掉两端多余的逗号 -->
    <set>
        <if test="empName != null">
            emp_name=#{empName},
        </if>
        <if test="empSalary &lt; 3000">
            emp_salary=#{empSalary},
        </if>
    </set>
    where emp_id=#{empId}
    <!--
         第一种情况:所有条件都满足 SET emp_name=?, emp_salary=?
         第二种情况:部分条件满足 SET emp_salary=?
         第三种情况:所有条件都不满足 update t_emp where emp_id=?
            没有set子句的update语句会导致SQL语法错误
     -->
</update>

4. trim 标签(了解)

  • 使用 trim 标签控制条件部分两端是否包含某些字符

    • prefix 属性:指定要动态添加的前缀
    • suffix 属性:指定要动态添加的后缀
    • prefixOverrides 属性:指定要动态去掉的前缀,使用“|”分隔有可能的多个值
    • suffixOverrides 属性:指定要动态去掉的后缀,使用“|”分隔有可能的多个值
<!-- List<Employee> selectEmployeeByConditionByTrim(Employee employee) -->
<select id="selectEmployeeByConditionByTrim" resultType="com.atguigu.mybatis.entity.Employee">
    select emp_id,emp_name,emp_age,emp_salary,emp_gender
    from t_emp

    <!-- prefix属性指定要动态添加的前缀 -->
    <!-- suffix属性指定要动态添加的后缀 -->
    <!-- prefixOverrides属性指定要动态去掉的前缀,使用“|”分隔有可能的多个值 -->
    <!-- suffixOverrides属性指定要动态去掉的后缀,使用“|”分隔有可能的多个值 -->
    <!-- 当前例子用where标签实现更简洁,但是trim标签更灵活,可以用在任何有需要的地方 -->
    <trim prefix="where" suffixOverrides="and|or">
        <if test="empName != null">
            emp_name=#{empName} and
        </if>
        <if test="empSalary &gt; 3000">
            emp_salary>#{empSalary} and
        </if>
        <if test="empAge &lt;= 20">
            emp_age=#{empAge} or
        </if>
        <if test="empGender=='male'">
            emp_gender=#{empGender}
        </if>
    </trim>
</select>

5. choose / when / otherwise 标签

  • 在多个分支条件中,仅执行一个。

    • 从上到下依次执行条件判断
    • 遇到的第一个满足条件的分支会被采纳
    • 被采纳分支后面的分支都将不被考虑
    • 如果所有的 when 分支都不满足,那么就执行 otherwise 分支
<!-- List<Employee> selectEmployeeByConditionByChoose(Employee employee) -->
<select id="selectEmployeeByConditionByChoose" resultType="com.atguigu.mybatis.entity.Employee">
    select emp_id,emp_name,emp_salary from t_emp
    where
    <choose>
        <when test="empName != null">emp_name=#{empName}</when>
        <when test="empSalary &lt; 3000">emp_salary &lt; 3000</when>
        <otherwise>1=1</otherwise>
    </choose>

    <!--
     第一种情况:第一个when满足条件 where emp_name=?
     第二种情况:第二个when满足条件 where emp_salary < 3000
     第三种情况:两个when都不满足 where 1=1 执行了otherwise
     -->
</select>

6. foreach 标签

6.1 基本用法
  • 用批量插入举例
<!--
    collection属性:要遍历的集合
    item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象
    separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符
    open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串
    close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串
    index属性:这里起一个名字,便于后面引用
        遍历List集合,这里能够得到List集合的索引值
        遍历Map集合,这里能够得到Map集合的key
 -->
<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
    <!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
    (#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
</foreach>
6.2 批量更新时需要注意
  • 上面批量插入的例子本质上是一条 SQL 语句,而实现批量更新则需要多条 SQL 语句拼起来,用分号分开。也就是一次性发送多条 SQL 语句让数据库执行。此时需要在数据库连接信息的 URL 地址中设置:
alex.dev.url=jdbc:mysql:///mybatis-example?allowMultiQueries=true
  • 对应的 foreach 标签如下:
<!-- int updateEmployeeBatch(@Param("empList") List<Employee> empList) -->
<update id="updateEmployeeBatch">
    <foreach collection="empList" item="emp" separator=";">
        update t_emp set emp_name=#{emp.empName} where emp_id=#{emp.empId}
    </foreach>
</update>
6.3 关于 foreach 标签的 collection 属性
  • 如果没有给接口中 List 类型的参数使用@Param 注解指定一个具体的名字,那么在 collection 属性中默认可以使用 collection 或 list 来引用这个 list 集合。这一点可以通过异常信息看出来:
Parameter 'empList' not found. Available parameters are [arg0, collection, list]
  • 在实际开发中,为了避免隐晦的表达造成一定的误会,建议使用@Param 注解明确声明变量的名称,然后在 foreach 标签的 collection 属性中按照@Param 注解指定的名称来引用传入的参数。

7. sql 片段

7.1 抽取重复的 SQL 片段
<!-- 使用sql标签抽取重复出现的SQL片段 -->
<sql id="mySelectSql">
    select emp_id,emp_name,emp_age,emp_salary,emp_gender from t_emp
</sql>
7.2 引用已抽取的 SQL 片段
<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>

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

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

相关文章

【【萌新的RiscV学习之在写代码之前对于关键路径的分析-11】】

萌新的RiscV学习之在写代码之前对于关键路径的分析-11 首先我们最简单的control 模块 全分段 因为只有分段 &#xff0c; 分开使用之后 &#xff0c; 各个阶段的具体功能才会合理使用 就像是为了后续 “气泡” 赋值 为 0 还有单独比较前递这种 EX &#xff1a; ALUOP ALUSrc …

Arcgis快速计算NDVI

Arcgis快速计算NDVI 一、问题描述 如何使用Arcgis像ENVI一样波段计算NDVI的值&#xff0c;事实上&#xff0c;Arcgis更快速一些。 二、操作步骤 首先准备好影像 打开窗口-影像分析 点击左上角 点击确定 &#xff08;发现自己使用的遥感影像不对劲&#xff0c;是计算好了…

智慧公厕有多智能?智慧厕所黑科技揭秘

随着科技的不断进步&#xff0c;智能化已经渗透到了我们生活的方方面面&#xff0c;智慧公厕也成为了时代的产物之一。那么&#xff0c;智慧公厕究竟有多智能呢&#xff1f;本文将以智慧公厕专业厂家广州中期科技有限公司&#xff0c;大量精品案例项目&#xff0c;以实景实图实…

idea技巧--debug使用技巧

写在前面&#xff1a; idea是java开发主流的ide&#xff0c;debug也是常用的功能&#xff0c;但这个功能有着很多强大好用的技巧。现在来总结一下。 文章目录 条件断点条件的时候求值并记录。命中后移除 基础debug简单的介绍 debug中求值强制返回断点回退 条件断点 从打断点…

HTML5+CSS3+JS小实例:鼠标滚轮水平滚动

实例:鼠标滚轮水平滚动 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="…

【深蓝学院】手写VIO第4章--基于滑动窗口算法的 VIO 系统:可观性和 一致性--笔记

0. 内容 由于我们是要做一个实时的定位系统&#xff0c;而不是SfM那种离线的三维重建的工作&#xff0c;所以需要在滑动窗口中不断地添加新数据以及删除旧数据&#xff0c;而前者可以把所有数据放在一个BA中求解。 1. 从高斯分布到信息矩阵 SLAM问题的建模&#xff0c;MAP->…

【卷积神经网络:Inception模型】

【卷积神经网络&#xff1a;Inception模型】 1 Inception模型的组成2 实现代码3 查看经典的Inceptioon模型 1 Inception模型的组成 Inception模型的组成主要由不同卷积核大小的卷积层拼接而成&#xff0c;其中一种带维度缩减的Inception模型可以减少参数量&#xff0c;引入更多…

javaee SpringMVC中json的使用

jsp <%--Created by IntelliJ IDEA.User: 呆萌老师:QQ:2398779723Date: 2019/12/6Time: 15:55To change this template use File | Settings | File Templates. --%> <% page contentType"text/html;charsetUTF-8" language"java" %> <%St…

OSI体系结构和TCP/IP体系结构

在第一章&#xff08; 计网第一章 &#xff09;的时候&#xff0c;曾经提到过OSI体系结构和TCP/IP体系结构&#xff0c;并对它们进行了简单的对比。这篇博客在其基础上进行更深层次的理解。 一.OSI体系结构&#xff1a; 通信子网&#xff1a; 计算机网络在逻辑功能上可以分为…

windows系统查看exe程序的依赖dll并拷贝到指定路径下

脚本 echo off REM windows_copy_depends.bat是脚本文件名&#xff0c;exe_path是exe文件的全路径&#xff0c;dll_folder_path是脚本当前路径下的文件夹名称 REM 如windows_copy_depends.bat E:\git_code\windows_docker_desktop\winget.exe 123 echo Usage: windows_copy_dep…

从零开始的C++(三)

1.引用与指针的相同与不同&#xff1a; 相同&#xff1a;底层逻辑相同&#xff0c;在汇编那层引用和指针是一致的&#xff0c;换句话说&#xff0c;引用就是被装饰后的指针&#xff0c;虽然外表有所差异&#xff0c;但内在是相同的。 不同&#xff1a; 1.定义的时候&#xf…

南京大学【软件分析】08 Pointer Analysis

文章目录 1. Motivation2. Introduction to Pointer Analysis3. Key Factors of Pointer Analysis3.1 Heap Abstraction3.2 Context Sensitivity3.3 Flow sensitivity3.4 Analysis scope 4. Concerned Statements 1. Motivation 指针分析存在不精确的问题。对于下面的例子&…

QT、C++实现地图导航系统(mapSystem)

文章目录 地图导航系统项目应用背景技术栈选择数据处理算法实现界面实现源码展示成果展示源码下载 &#xff08;免费&#xff09; 地图导航系统 项目应用背景 电子地图导航系统的主要目的是为用户提供精确、实时的导航和位置信息&#xff0c;以帮助他们在城市或地区内轻松找到…

C++ - 封装 unordered_set 和 unordered_map - 哈希桶的迭代器实现

前言 unordered_set 和 unordered_map 两个容器的底层是哈希表实现的&#xff0c;此处的封装使用的 上篇博客当中的哈希桶来进行封装&#xff0c;相当于是在 哈希桶之上在套上了 unordered_set 和 unordered_map 。 哈希桶的逻辑实现&#xff1a; C - 开散列的拉链法&…

Java环境配置无效

Java环境配置无效 老是使用1.8版本&#xff0c;象牛皮癣。 查找java来源 where java 打开C:\Windows\System32 删掉java.exe javaaw.exe javaaws.exe 正常

【超强图解Docker常见命令与实战】

目录 一、镜像容器基础&#xff08;一&#xff09;基本概念&#xff08;二&#xff09;镜像&#xff08;三&#xff09;容器&#xff08;四&#xff09;运行的容器&#xff08;五&#xff09; 镜像层(image layer) 二、常用命令&#xff08;一&#xff09;docker create <im…

XWiki Platform 安全漏洞RCE:CVE-2023-37462

2023年7月14日&#xff0c;美国国家标准与技术研究院&#xff08;NIST&#xff09;维护的综合性漏洞数据库&#xff08;NVD&#xff09;第一次记录了这个漏洞&#xff0c;这个漏洞影响版本是从7.0到14.48&#xff08;不包括&#xff09;和从14.5到14.10.4&#xff08;不包括&am…

BGP服务器租用价格表_腾讯云PK阿里云

BGP云服务器像阿里云和腾讯云均是BGP多线网络&#xff0c;速度更快延迟更低&#xff0c;阿里云BGP服务器2核2G3M带宽优惠价格108元一年起&#xff0c;腾讯云BGP服务器2核2G3M带宽95元一年起&#xff0c;阿腾云分享更多云服务器配置如2核4G、4核8G、8核16G等配置价格表如下&…

A*搜索算法(含Java源代码)

前言 本来是想写一块的&#xff0c;但是为了这个国庆的专属勋章就分开写了&#xff0c;这个侧重还是对作业题目要求的实现。 课题目的 理解 A Star 算法设计流程。 理解 A Star 算法的启发式函数的作用。 掌握 A Start 解决搜索问题的过程&#xff0c;能够应用 A Star 算法…

凉鞋的 Godot 笔记 101. Hello Godot!

101. Hello Godot 学习任何一门技术&#xff0c;第一件事就是先完成 Hello World&#xff01;的输出 所以我们也来先完成 Godot 的 Hello World。 我们所使用的 Godot 版本是 4.x 版本。 安装的过程就不给大家展示了&#xff0c;笔者更推荐初学者用 Steam 版本的 Godot&…