Mybatis----多表查询

news2024/11/19 22:36:57

目录

返回类型

resultType

resultMap

1、字段映射

 2、多表查询

 动态SQL

if标签

 where标签

 set标签

 choose(when,otherwise) 语句

trim标签

for-each标签

 SQL片段


返回类型

resultType

Mybatis在查询时,一定要指定返回类型;而其他操作,默认返回修改数目

在正常情况下,我们查询使用resultType返回查询结果是可以的

但是,也有其他情况是resultType不能解决的

如果说,类和数据库的参数不匹配,那么查询出来的结果在填充到类对象时,就会找不到对应的字段,(数据库的结果根据数据库列名和类字段名称进行匹配赋值)

数据库的列名是class_id,而类字段是 stu_class,mybatis不能将这两个联系起来,这时就需要使用resultMap

resultMap

1、数据库列名和类字段名称不匹配,可以使用resultMap来配置映射关系

2、resultMap可以用来处理多表联查

1、字段映射

<?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.example.demo.Mapper.SelectById">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->
    <resultMap id="Map" type="com.example.demo.Model.Student">
<!--        id标识这个resultMap,可以和数据库查找时id绑定,引用这个resultMap-->
<!--        type表示resultMap映射到的实体类-->


        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="class_id" property="stu_class"></result>

<!--        id标识主键的映射 -->
<!--        result标识其他字段的映射-->
<!--        column表示数据库的字段,property表示类的字段,将数据库的列名和类字段联系起来-->

    </resultMap>

    <select id="selectById" resultMap="Map">
        <!--        这个id,表示实现StudentMapper接口的哪一个方法-->
        <!--        resultMap 表示方法的返回类型,使用id绑定到上述的resultMap-->

        select * from student where id=#{id}
        <!--        这里写具体的执行语句-->
    </select>

</mapper>

这时,我们来运行单元测试:

 2、多表查询

一个学生属于一个班级,一对一

1、创建Class类,Student类增加Class类的变量

@Data
public class Class {
    private Integer class_id;
    private String class_name;
}
@Data
public class Student {
    private Integer id;
    private String name;
    private Integer class_id;
    private Class stu_class;
}
<?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.example.demo.Mapper.SelectAll">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

<!--    Class类的映射-->
<resultMap id="classMap" type="com.example.demo.Model.Class">
    <result column="class_id" property="class_id"></result>
    <result column="class_name" property="class_name"></result>
</resultMap>



    <resultMap id="StudentMap" type="com.example.demo.Model.Student">
        <!--        id标识这个resultMap,可以和数据库查找时id绑定,引用这个resultMap-->
        <!--        type表示resultMap映射到的实体类-->

        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="class_id" property="class_id"></result>
        <!--        id标识主键的映射 -->
        <!--        result标识其他字段的映射-->
        <!--        column表示数据库的字段,property表示类的字段,将数据库的列名和类字段联系起来-->

<!--        association实现一对一多表查询的映射关系 -->
<!--        id 表示Student类中创建的Class对象的变量名称,resultMap表示class类的映射关系,会将查询到的Class数据按照此形式填充
            columnPrefix给数据库起别名,这样可以避免两个表有重名列时,数据重复的情况(第二个表id应该是2,第一个表id为1,因为同名,第二个表的id就变成了第一个表id的值 查询错误) -->
        <association property="stu_class" resultMap="classMap" columnPrefix="c_">

        </association>

    </resultMap>

    <select id="selectAll" resultMap="StudentMap">
        <!--        这个id,表示实现StudentMapper接口的哪一个方法-->
        <!--        resultMap 表示方法的返回类型,使用id绑定到上述的resultMap-->

<!--        class表的属性重命名-->
        select student.*,class.class_id c_class_id,class.class_name c_class_name from student,class where student.class_id=#{class_id} and class.class_id=#{class_id}
        <!--        这里写具体的执行语句-->
    </select>

</mapper>

 一个班级可以有多个学生 一对多

@Data
public class Student {
    private Integer id;
    private String name;
    private Integer class_id;
}
@Data
public class Class {
    private Integer class_id;
    private String class_name;
    private List<Student> list;
}
<?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.example.demo.Mapper.SelectAllStudents">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

    <resultMap id="StudentMap" type="com.example.demo.Model.Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="class_id" property="class_id"></result>
    </resultMap>


    <!--    Class类的映射-->
    <resultMap id="classMap" type="com.example.demo.Model.Class">
        <result column="class_id" property="class_id"></result>
        <result column="class_name" property="class_name"></result>
        <collection property="list" resultMap="StudentMap" columnPrefix="s_"></collection>
        <!-- property 绑定字段  将student表以s_重命名-->
    </resultMap>


    <select id="selectAllStudents" resultMap="classMap">

        select class.*, student.id s_id,student.name s_name,student.class_id s_class_id from class,student where student.class_id=#{class_id} and class.class_id=#{class_id}
        <!--        这里写具体的执行语句-->
    </select>

</mapper>

 动态SQL

如果有比较复杂的业务,我们需要写复杂的 SQL 语句,往往需要拼接,而拼接 SQL ,稍微不注意,由于引号,空格等缺失可能都会导致错误。

那么怎么去解决这个问题呢?这就要使用 mybatis 动态SQL,通过 if, choose, when, otherwise, trim, where, set, foreach等标签,可组合成非常灵活的SQL语句,从而在提高 SQL 语句的准确性的同时,也大大提高了开发人员的效率。

if标签

根据name和class_id来查询学生信息

<?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.example.demo.Mapper.SelectStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

    <select id="selectStudent" resultType="com.example.demo.Model.Student">

       select * from student where name=#{name} and class_id=#{class_id}
    </select>

</mapper>

 如果class_id为空,那么就是select * from student where name=#{name} and class_id=null;

 如果name为空,那么就是select * from student where name= and class_id=#{class_id};这是错误的写法,我们这时就要用到if标签

<?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.example.demo.Mapper.SelectStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

    <select id="selectStudent" resultType="com.example.demo.Model.Student">

       select * from student where
        <if test="name!=null">
            name=#{name}
        </if>
        <if test="class_id!=null">
            and class_id=#{class_id}
        </if>


    </select>

</mapper>

  如果class_id为空,那么就是select * from student where name= #{name}; 

 如果name为空,那么就是select * from student where  and class_id=#{class_id};这是错误的写法,要使用到where标签

 where标签

where标签就是为sql加上where关键字,且会自动的多余的and、or关键字,当所有的条件都不成立的时候,where标签也不会生成

去掉前面的and,不会去掉后面的and

<?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.example.demo.Mapper.SelectStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

    <select id="selectStudent" resultType="com.example.demo.Model.Student">

       select * from student
        <where>
        <if test="name!=null">
            name=#{name}
        </if>
        <if test="class_id!=null">
            and class_id=#{class_id}
        </if>
        </where>

    </select>

</mapper>

 set标签

set元素会动态前置SET关键字,同时也会自动抹去where查询条件前多余的逗号,避免因为使用条件语句在生成赋值语句的后面留下不需要的逗号

<?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.example.demo.Mapper.UpdateStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

    <update id="updateStudent" >

   update student
        <set>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="name!=null">
                 ,name=#{name}
            </if>
        </set>

    </update>

</mapper>

 choose(when,otherwise) 语句

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

<?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.example.demo.Mapper.SelectByChoices">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

    <select id="selectByChoices" resultType="com.example.demo.Model.Student">

        select * from student where
   <choose>
       <when test= "id!=null">id=#{id}</when>
       <when test="name!=null">name=#{name}</when>
       <otherwise > class_id=#{class_id}</otherwise>
   </choose>
    </select>

</mapper>

when相当于if,otherwise相当于else

也就是说,这里我们有三个条件,id,name,class_id,只能选择一个作为查询条件

如果 id 不为空,那么查询语句为:select * from student where  id=?

如果 id 为空,那么看name 是否为空,如果不为空,那么语句为 select * from student where  name=?;

如果 name 为空,那么查询语句为 select * from student where class_id=?

trim标签

用于去掉某些内容

  • prefix表示语句块,以prefix值为前缀
  • suffix表示语句块,以suffix值为后缀
  • prefixOverrides表示语句块,要去除的前缀
  • suffixOverrides表示语句块,要去除的后缀

用 trim 改写上面的 if+where 语句

 <select id="selectStudent" resultType="com.example.demo.Model.Student">
        select * from student

        <trim prefix="where" prefixOverrides="or|and">
            <if test="name!=null">
                name=#{name}
            </if>
            <if test="class_id!=null">
                and class_id=#{class_id}
            </if>
        </trim>
<!--        trim prefix="where" prefixOverrides="or|and" 表示trim标签的语句内,拼接where,去除or、and前缀  -->

    </select>

 用 trim 改写上面的 set 语句

<?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.example.demo.Mapper.UpdateStudent">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

<!--    <update id="updateStudent" >-->

<!--   update student-->
<!--        <set>-->
<!--            <if test="id!=null">-->
<!--                id=#{id}-->
<!--            </if>-->
<!--            <if test="name!=null">-->
<!--                 ,name=#{name}-->
<!--            </if>-->
<!--            <trim prefix="" suffix="" prefixOverrides="" suffixOverrides="">-->

<!--            </trim>-->
<!--        </set>-->

<!--    </update>-->

    <update id="updateStudent" >
        update student
        <trim prefix="set" prefixOverrides="," suffixOverrides=",">
            <if test="id!=null">
                id=#{id},
            </if>
            <if test="name!=null">
                name=#{name},
            </if>
        </trim>
    </update>

</mapper>

for-each标签

 这样写的时候,就要多次 id=#{id},可以使用foreach标签实现循环

<?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.example.demo.Mapper.DeleteSomeStudents">
    <!-->namespace 绑定xml文件实现的接口 包名+类名  <-->

<!--    <delete id="delete" >-->
<!--        delete from student where id=#{id} or id=#{id1} or id=#{id2}-->
<!--    </delete>-->

    <delete id="delete">
<!--        id绑定方法-->
        delete  from student
        <where>
            <!--
                collection:指定输入对象中的集合 例如list,map,或者set 对象
                item:每次遍历生成的对象 我们枚举时是id,id1,id2 而item类似于for循环的变量i
                open:开始遍历时的拼接字符串
                close:结束时拼接的字符串
                separator:遍历对象之间需要拼接的字符串

                 delete from student where id=#{id} or id=#{id1} or id=#{id2}

              -->
            <foreach collection="list" item="id" open="(" close=")" separator="or">
                <if test="id!=null">
                id=#{id}
<!--                delete from student where ( id={#id} or id=#{id} or id=#{id} ) 这里的#{id}是循环遍历的值-->
                </if>
            </foreach>

        </where>
    </delete>
</mapper>

 SQL片段

如果某一SQL的使用频率很高,我们可以把他单独定义,提供代码复用率

1、定义SQL

   <sql id="selectStudentByTd_SQL">
        select * from student
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
        </where>
    </sql>

2、引用SQL


    <select id="selectById" resultType="com.example.demo.Model.Student">
       <!-- 如果refid 指定的不在本文件中,给引用前缀加上namespace,指定SQL片段所在文件 所对应的接口-->
        <include refid="com.example.demo.Mapper.DeleteSomeStudents.selectStudentByTd_SQL"></include>
    </select>

 

 

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

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

相关文章

BH1750 传感器实战教学 —— 硬件设计篇

前言 前面刚写了一篇 《BH1750 光照传感器文档详解 及 驱动设计》&#xff0c;今天来写一篇简单的传感器实战教学。 文章如下&#xff1a;BH1750 光照传感器文档详解 及 驱动设计 那有些朋友就疑惑了&#xff0c;在上一篇文章其实我们基本都测试成功了&#xff0c;驱动也写了…

现代操作系统原理与实现

突然更新&#xff0c;为了水一个1024徽章拿随书笔记来发发&#xff08;嘿嘿 原文链接&#xff1a;https://github.com/yanyanran/YBlog/blob/main/%E7%8E%B0%E4%BB%A3%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E7%8E%B0.md 一、操作系统结构…

【网络安全篇】JavaSript基础内容大全

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;学习JavaSript基础 ✅创作者&#xff1a;贤鱼 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;贤鱼的个人主页 &#x1f525;专栏系列&#xff1a;网络安全 JavaSript基础大全&#x1f340;java和JavaSri…

[C]带你了解C语言是如何操作文件的

文章目录一、认识文件1.1 为什么要使用文件1.2 什么是文件1.3 文件名1.4 文件指针1.5 文件的打开和关闭二、文件的顺序读写2.1 fgetc和fputc2.2 fgets和fputs2.3 fscanf和fprintf2.4 fread和fwrite2.5 对比一组函数三、文件的随机读写3.1 fseek3.2 ftell3.3 rewind四、文本文件…

高云FPGA系列教程(5):ARM点灯工程设计

文章目录[toc]1. ARM核定制2. ARM核程序设计3. ARM程序烧写4. 工程下载本文是高云FPGA系列教程的第5篇文章。 前面几篇笔记都是介绍的高云GW1NSR-4C FPGA部分的使用&#xff0c;本篇文章介绍片上ARM Cortex-M3硬核处理器的使用&#xff0c;演示如何定制一颗ARM处理器硬件&#…

大数据电信客服-数据采集/消费(二)

目录 一、数据采集/消费(存储) 二、数据采集 三、数据消费 四、编写代码 在project-ct.pom 在ct.consume下 在ct.consumer.bean 在ct.consumer.dao 在ct-consumer的resources 在ct-common.pom 在ct.common.api 在ct.common.bean 在ct.common.constant 在ct-common的…

LQ0123 小朋友崇拜圈【DFS】

题目来源&#xff1a;蓝桥杯2018初赛 C C组G题 题目描述 班里N个小朋友&#xff0c;每个人都有自己最崇拜的一个小朋友&#xff08;也可以是自己&#xff09;。 在一个游戏中&#xff0c;需要小朋友坐一个圈&#xff0c; 每个小朋友都有自己最崇拜的小朋友在他的右手边。 求满…

vue06安装vue-cli+使用vue-cli搭建项目+什么是*.vue文件+开发示例+必问面试知识点

目录 1. vue-cli安装 1.1 安装前提 1.2 什么是vue-cli 1.3 安装vue-cli 2. 使用vue-cli构建项目 2.1 使用脚手架创建项目骨架 2.2 到新建项目目录&#xff0c;安装需要的模块 2.3 如何修改端口号 2.4 添加element-ui模块 2.5 package.json详解 3. install命令中的-g…

腾讯云~ zookeeper集群安装、配置、验证

文章目录一、 预备工作1. 下载2. 解压3. 创建目录4. myid 文件5. 验证6. 效果图二、配置管理2.1. zoo1.cfg2.2. zoo2.cfg2.3. zoo3.cfg2.4. 防火墙2.5. 启动zk2.6. 运行状态一、 预备工作 1. 下载 cd /app wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.12/…

GitLab API 的使用教程

1 简介 GitLab 作为一个开源、强大的分布式版本控制系统&#xff0c;已经成为互联网公司、软件开发公司的主流版本管理工具。使用过 GitLab 的都知道&#xff0c;想要提交一段代码&#xff0c;可以通过 git push 提交到远程仓库&#xff0c;也可以直接在 GitLab 平台上修改提交…

基于华为云IOT平台实现多节点温度采集(STM32+NBIOT)

一、前言 当前的场景是&#xff0c;在高速公路上部署温度采集设备&#xff0c;在高速路地表安装温度检测传感器&#xff0c;检测当前路段的路面实际温度。一段高速路上有多个地点需要采集温度数据。 采集温度数据需要上传到云平台进行数据存储&#xff0c;并且通过可视化界面展…

七万字整理SpringCloud + CloudAlibaba知识点总结笔记

各位小伙伴们大家好&#xff0c;欢迎来到这个小扎扎的spring cloud专栏&#xff0c;在这个系列专栏中我对B站尚硅谷阳哥的spring cloud教程进行一个总结&#xff0c;鉴于 看到就是学到、学到就是赚到 精神&#xff0c;这波依然是血赚 ┗|&#xff40;O′|┛ SpringCloud Clou…

Linux文件系统inode的作用

目录 前言 简介 inode与block 1、查看文件的inode信息 2、查看分区中的inode节点数 前言 前面学习了磁盘管理中的磁盘分区&#xff0c;以及逻辑卷&#xff0c;交换分区的创建&#xff0c;这篇文章将介绍一下我们在分区以及格式化时候用到的ext4文件系统&#xff0c;本盘文…

【云原生之Docker实战】使用Docker部署ShowDoc文档工具

【云原生之Docker实战】使用Docker部署ShowDoc文档工具一、ShowDoc介绍1.ShowDoc简介2.ShowDoc功能二、检查docker版本三、检查docker状态四、下载ShowDoc镜像五、创建ShowDoc容器1.创建数据目录2目录授权3.运行ShowDoc容器4.查看ShowDoc容器状态5.查看容器运行日志六、ShowDoc…

【精通Java篇 | IO流】详讲字节流与常用方法

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;喜欢编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc…

Java流式编程stream

文章目录一、简介二、创建Stream三、常用操作四、其他操作一、简介 流式 API 从 Java8 开始引入&#xff0c;支持链式书写。 流只能消费一次&#xff0c;不能被两次消费&#xff08;两次最终操作&#xff09; 流在管道中流通&#xff0c;在节点被处理。 流【无存储】&#x…

vim如何进行批量化注释及取消,也在1024表明自己算十分之一的程序员

前言 &#x1f47b;作者&#xff1a;龟龟不断向前 &#x1f47b;简介&#xff1a;宁愿做一只不停跑的慢乌龟&#xff0c;也不想当一只三分钟热度的兔子。 &#x1f47b;专栏&#xff1a;C初阶知识点 &#x1f47b;工具分享&#xff1a; 刷题&#xff1a; 牛客网 leetcode笔记软…

人家网站都免费了,你还用Python去爬?

文章目录⛳️ 实战场景⛳️ 实战编码⛳️ 实战场景 这次实战的目标是一个叫做猫肯的字体站点&#xff0c;该站点所有的字体都是免费可商用的&#xff0c;所以为什么还要去下载呢&#xff1f; 答案是练手&#xff0c;借免费站点学习爬虫&#xff0c;&#x1f30b; 目标站点地址…

Python爬虫技术系列-05字符验证码识别

Python爬虫技术系列-05字符验证码识别1. 光学文字识别1.1 OCR概述1.2 OCR识别库Tesseract下载安装1.3 生成验证码图片1.4 字符验证码识别1.安装python识别验证码库&#xff1a;2.验证码识别&#xff1a;1.5 使用打码平台识别验证码1.6 滑动验证码识别1. 光学文字识别 1.1 OCR概…

卡尔曼滤波实例——预测橘子的轨迹

目录 流程 一、采用轮廓的方式检测橘子位置 &#xff08;一&#xff09;滚动条获取阈值 &#xff08;二&#xff09;获取到图像中的包围橘子对应的白色图形的最小矩形框的信息 二、获取橘子检测框的质心 三、将质心送入卡尔曼滤波器&#xff0c;获取下一次的质心位置 四…