二 动态SQL和多对一,一对多

2023-10-28

10、多对一处理

子查询,联表查询

  • 多个学生,对应一个老师
  • 对于学生这边而言,关联(association)多个学生,关联一个老师【多对一】
  • 对于老师而言,集合(Collection),一个老师,有很多学生【一对多】

测试环境搭建

  1. 导入lombok

  2. 新建实体类 Teacher,Student

    public class Teacher {
        private int id;
        private String name;
    }
    
    public class Student {
        private int id;
        private  String name;
       //学生要关联一个老师
        private Teacher teacher;
      }
    
  3. 建立Mapper接口

  4. 建立Mapper.XML文件

  5. 在核心配置文件中绑定注册我们的Mapper接口或者文件!【方式很多,随心选】

  6. 测试查询是否能够成功!

按照查询嵌套处理(子查询)

<!--
    思路:
        1. 查询所有的学生信息
        2. 根据查询出来的学生的tid,寻找对应的老师!  子查询
    -->

<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>

<resultMap id="StudentTeacher" type="Student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--复杂的属性,我们需要单独处理 对象: association 集合: collection -->
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>

<select id="getTeacher" resultType="Teacher">
    select * from teacher where id = #{id}
</select>

按照结果嵌套处理(联表查询)

<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
    select  s.id sid ,s.name sname,t.name tname
    from student s,teacher t
    where s.tid=t.id
</select>
    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>

11、一对多

比如:一个老师拥有多个学生! 对于老师而言就是一对多的关系!

实体类

@Data
public class Teacher {
    private int id;
    private String name;
    //一个老师拥有多个学生
    private List<Student> students;
}
@Data
public class Student {
    private int id;
    private  String name;
    private int tid;
  }

按照结果嵌套处理

    <!--按结果嵌套查询-->
    <select id="getTeacher" resultMap="TeacherStudent">
        select s.id sid, s.name sname, t.name tname,t.id tid
        from student s,teacher t
        where s.tid = t.id and t.id = #{tid}
    </select>

    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <!--复杂的属性,我们需要单独处理 对象: association 集合: collection
        javaType="" 指定属性的类型!
        集合中的泛型信息,我们使用ofType获取
        -->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>

按照查询嵌套处理

<select id="getTeacher2" resultMap="TeacherStudent2">
    select * from mybatis.teacher where id = #{tid}
</select>

<resultMap id="TeacherStudent2" type="Teacher">
    <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>

<select id="getStudentByTeacherId" resultType="Student">
    select * from mybatis.student where tid = #{tid}
</select>

小结

  1. 关联 - association 【多对一】
  2. 集合 - collection 【一对多】
  3. javaType 和 ofType
    1. JavaType 用来指定实体类中属性的类型
    2. ofType 用来指定映射到List或者集合中的 pojo类型,泛型中的约束类型!

注意点

  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一中,属性名和字段的问题!
  • 如果问题不好排查错误,可以使用日志

在这里插入图片描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lGPhwmg0-1653313325896)(D:\Typora\Spring\image-20220522165725183.png)]

面试必考

  • Mysql引擎
  • InnoDB底层原理
  • 索引
  • 索引优化!

12、动态 SQL

什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
if
choose (when, otherwise)
trim (where, set)
foreach

实体类

@Data
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;//属性名和字段名不一致 mapUnderscoreToCamelCase开启驼峰命名
    private int views;
}

UUID 便于生成,不会重复,在分布式架构的系统中,很常见,但对于使用了mysql innodb 存储引擎来说,UUID 则不是一个好的选择。

public static  String getID(){
    //主键
    return UUID.randomUUID().toString().replaceAll("-","");
}

添加数据

@Test
public void addBlog(){
    SqlSession sqlSession= MybatisUtils.getSqlSession();
    BlogMapper mapper=sqlSession.getMapper(BlogMapper.class);
//在数据库中添加数据
    Blog blog=new Blog();
    blog.setId(IDUtils.getID());
    blog.setTitle("mybatis");
    blog.setAuthor("loveyourself");
    blog.setCreateTime(new Date());
    mapper.addBlog(blog);

    blog.setId(IDUtils.getID());
    blog.setTitle("spring");
    mapper.addBlog(blog);

    blog.setId(IDUtils.getID());
    blog.setTitle("springboot");
    mapper.addBlog(blog);

    blog.setId(IDUtils.getID());
    blog.setTitle("springCloud");
    mapper.addBlog(blog);
    sqlSession.close();
}

IF

//查询博客
List<Blog> queryBlogIF(Map map);
<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from mybatis.blog
    where 1=1
    <if test="title!=null">
        and title=#{title}
    </if>
    <if test="author!=null">
        and author=#{author}
    </if>
</select>

测试

@Test
public void queryBlogIF() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Map<String, String> map = new HashMap<>();
    map.put("title", "mybatis");
    map.put("author","loveyourself");
    List<Blog> list=mapper.queryBlogIF(map);
    for (Blog s:list){
        System.out.println(s);
    }
    sqlSession.close();
}

choose (when, otherwise)

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<!-- 类似于java中的case智慧选择其中一个去实现-->
<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from mybatis.blog
   <where>
       <choose>
           <when test="title!=null">
               title=#{title}
           </when>
           <when test="author!=null">
               and author=#{author}
           </when>
            <otherwise>
                and views=#{views}
            </otherwise>
       </choose>
   </where>
</select>

trim (where,set)

动态更新语句set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

<update id="updateBlog" parameterType="map">
    update mybatis.blog
    <set>
        <if test="title!=null">
            title=#{title}
        </if>
        <if test="author!=null">
            and author=#{author}
        </if>
    </set>
where id=#{id}
</update>

所谓动态sql本质还是sql语句,只是我们可以在sql层面,去执行一些逻辑代码

SQL片段

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!

  1. 使用SQL标签抽取公共的部分

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
    
  2. 在需要使用的地方使用Include标签引用即可

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>
    

注意事项:

  • 最好基于单表来定义SQL片段!
  • 不要存在where标签(就用if的就挺好)

foreach

动态SQL的另外一个常用的操作需求是对一个集合进行遍历,通常实在构建IN条件语句的时候。

foreach元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头于结尾的字符串以及在迭代结果之间反之分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qc9C0hiY-1653313325901)(D:\Typora\Spring\image-20220523210620674.png)]

<!--
原生 select * from mybatis.blog where 1=1 and (id=1 or id = 2 or id=3)
    我们传递一个万能的map,这个map中可以存在一个集合collection
    open开头是什么,close结尾是什么,separator分隔符是什么
-->
    <select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <foreach item="id" collection="ids" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>
@Test
public void queryBlogForeach(){
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    BlogMapper mapper=sqlSession.getMapper(BlogMapper.class);
    Map map=new HashMap();
    List<Integer> ids=new ArrayList<Integer>();
    ids.add(1);
    ids.add(3);
    map.put("ids",ids);
    List<Blog> list=mapper.queryBlogForeach(map);
    sqlSession.close();
}

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性按照SQL的格式,去排列组合就可以了

就是:现在Mysql中写出完整的SQL,再对应的去修改成为我们的动态SQL实现通用即可!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二 动态SQL和多对一,一对多 的相关文章

随机推荐

  • logstash快速安装插件并打离线包

    一 背景 1 生产环境是不能直接联网的 2 要给 Logstash 安装上 logstash input jdbc 插件用来读取 Mysql 数据到 ES 进行全文检索 二 原生安装 usr share logstash bin logst
  • 预加重、去加重和均衡

    预加重 去加重和均衡 随着信号速率的增加 高速信号的趋肤效应和传输线的介质损耗 使信号在传输 过程中受损很大 为了在接收终端能得到比较好的波形 就需要对受损的信号进 行补偿 常用的补偿技术有 预加重 去加重和均衡在介绍这三种信号补偿技术 之
  • Mysql-错误处理: Found option without preceding group in config file

    1 问题描述 安装MYSQL时 在cmd中 初始化 数据库时 输入命令 mysqld initialize console cmd报错 D mysql 8 0 19 winx64 bin gt mysql initialize consol
  • 如何读取redis中的key值中的结果

    redis的值有5种类型 不同的类型有不同的命令来获取 字符直接 get key 队列 左端弹出一个元素 LPOP key 哈希 HGET key field 集合 SMEMBERS key 返回集合中的所有元素 有序集合ZRANGE ke
  • 【python】mac+appium获取安卓app的appPackage和appActivity

    本文介绍两种亲测最简单有效的办法 方法一 如果你有一台mac本和win的电脑 但是想用mac测安卓app 在win的电脑上解压后缀为 apk的文件 用notepad 等打开解压后文件夹中的AndroidManifest xml即可看到app
  • 内测体验:JetBrains面向未来的Fleet编辑器是什么+究竟怎样 使用初体验+与vsc对比

    异想之旅 本人原创博客完全手敲 绝对非搬运 全网不可能有重复 本人无团队 仅为技术爱好者进行分享 所有内容不牵扯广告 本人所有文章仅在CSDN 掘金和个人博客 一定是异想之旅域名 发布 除此之外全部是盗文 引言 上个月 我在看到某公众号推广
  • Connected Components?【Codeforces 920E】【补图的联通块的个数】

    Educational Codeforces Round 37 Rated for Div 2 E 怎么说呢 跟这道题是一样的 这道题就变得很模板了 原题 include
  • Unity2D input.GetAxis()与input.GetAxisRaw()的相同点、区别以及简单用法

    目录 前言 一 input GetAxis 与input GetAxisRaw 的相同点 区别 二 简单用法 1 input GetAxis 2 input GetAxisRaw 三 总结 前言 input GetAxis 与input G
  • v-model的使用

    目录 一 v model 的原理 二 v model 结合radio 使用 三 v model 结合checkbox 类型单选使用 四 v model 结合checkbox 多选使用 五 v model 结合select 使用 六 v mo
  • 消灭兔子【贪心+堆】

    题目链接 51nod 1191 消灭兔子 兔子这么可爱 怎么能消灭呢 我们可以用贪心的办法来解决这个问题 因为每个箭只能使用一次 所以 我们将兔子血量从高往低排列 先做掉高血量兔子 然后再看低血量兔子 保证了伤害高但是价值小的武器假如在之前
  • 编程实现RSA数字签名

    一 实验目的 理解RSA数字签名 并运用编程实现RSA数字签名 二 实验过程 1 学习RSA算法及RSA数字签名算法流程 2 RSA数字签名原理 当发送方想要给接收方发送数据 并想进行数字签名的时候 发送方只需要利用自己的私钥 对数据进行数
  • python进阶:线程、进程和协程

    前言 线程 进程和协程都是实现多任务 同一时间可以做多个事情就叫做多任务 的方法 并发 一段时间内做不同的事情 比如一个人吃饭喝水 吃的时候不能喝 喝的时候不能吃 只有在一段时间 吃了再喝或者喝了在吃 并行 同一时间做不同的事情 比如边听音
  • 谈乱序执行和内存屏障

    10多年前的程序员对处理器乱序执行和内存屏障应该是很熟悉的 但随着计算机技术突飞猛进的发展 我们离底层原理越来越远 这并不是一件坏事 但在有些情况下了解一些底层原理有助于我们更好的工作 比如现代高级语言多提供了多线程并发技术 如果不深入下来
  • [Linux]Kali安装Deepin-wine-WeChat

    Kali版本 2022 2 KDE环境 实体机 wget O https deepin wine i m dev setup sh sh apt get install com qq weixin deepin 其他的QQ TIM登录后会崩
  • python PyAV库解析H264视频流及保存指定帧

    PyAV是一个视频处理库 可用于读取 写入和处理视频 要使用PyAV读取视频关键帧 首先需要安装PyAV 可以使用以下命令安装PyAV pip install av 安装完成后 您可以使用以下代码打开视频文件并读取关键帧 import av
  • python数据可视化第八章使用matplotlib绘制高级图表

    使用matplotlib绘制高级图表 1 绘制高等图 等高线图是地形图上高程相等的相邻各点所连成的j闭合曲线 它会将地面上海拔高度相同的点连成环线 之后将环线垂直投影到某一水平面上 并按照 定的比例缩绘到图纸上 常见于山谷 山峰或梯度下降算
  • CloudOS:物联网开发平台,云上开发,边端交付

    什么是物联网 物联网 Internet of Things 简称IoT 是指通过各种信息传感器 射频识别技术 全球定位系统 红外感应器 激光扫描器等各种装置与技术 实时采集任何需要监控 连接 互动的物体或过程 采集其声 光 热 电 力学 化
  • iOS开发中,使用PC查看/修改沙盒文件

    简介 在进行iOS开发中 APP尤其是游戏 在沙盒中可以存放游戏资源包或者数据 例如Json文件 AssetBundle包 在使用服务器下载资源包 存放到本地沙盒中 可以大大减少APP本身的大小 当然 在调试的时候 如果频繁的更换服务器的A
  • 处理告警“ warning #69-D integer conversion resulted in truncation”的方法

    今天分享一个常见的语法告警 就是实参与形参的类型参数对于不上 错误之处 首先我们先看一下告警提示 告警 c 49 warning 69 D integer conversion resulted in truncation 其翻译过来意思就
  • 二 动态SQL和多对一,一对多

    二 动态SQL和多对一 一对多 10 多对一处理 测试环境搭建 按照查询嵌套处理 子查询 按照结果嵌套处理 联表查询 11 一对多 按照结果嵌套处理 按照查询嵌套处理 小结 12 动态 SQL IF choose when otherwis