写点什么

【SSM】Mybatis 系列——多对一和一对多的处理、动态 SQL

作者:胖虎不秃头
  • 2022 年 9 月 15 日
    河南
  • 本文字数:4045 字

    阅读完需:约 13 分钟

【SSM】Mybatis系列——多对一和一对多的处理、动态SQL

10 多对一处理


多个学生,对应老师


对于这边而言,关联 多个学生,关联一个老师【多对一】


对于老师而言,集合 一个老师,有很多学生 【一对多】


CREATE TABLE `teacher`( `id` INT(10) NOT NULL, `name` VARCHAR (30) DEFAULT NULL, PRIMARY KEY(`id`))ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO teacher(`id`, `name`) VALUES(1,'秦老师');
CREATE TABLE `student`( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, `tid` INT(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`))ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `student` (`id`, `name`, `tid`) VALUES('2', '小亮', '1');INSERT INTO `student` (`id`, `name`, `tid`) VALUES('3', '小黑', '1');INSERT INTO `student` (`id`, `name`, `tid`) VALUES('4', '小白', '1');INSERT INTO `student` (`id`, `name`, `tid`) VALUES('5', '小雨', '1');INSERT INTO `student` (`id`, `name`, `tid`) VALUES('6', '小哥', '1');
复制代码

10.1 测试环境搭建

  • 导入 lombok

  • 新建实体类 Teacher、Student

  • 建立 Mapper 接口

  • 建立 Mapper.xml 文件

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

  • 测试查询成功与否

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

<!--     思路:        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-->    <collection property="teacher" column="tid" javaType="teacher" select="getTeacher"/></resultMap><select id="getTeacher" resultType="teacher">    select * from teacher where id = #{id}</select>
复制代码

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

<!--按照结果进行查询--><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"></result> </association></resultMap>
复制代码


10.4 Mysql 多对一查询方式:


  • 子查询 (按照查询嵌套)

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

11 一对多处理

比如:一个老师有多个学生!


对于老师而言,就是一对多的关系!

1、环境搭建

环境搭建,和刚才一样实体类


@Datapublic class Student {    private int id;    private String name;    private int tid;}
复制代码


@Datapublic class Teacher {    private int id;    private String name;//一个老师拥有多个学生private List<Student> student;}
复制代码

2、按照结果嵌套查询

<!--按照结果嵌套处理-->    <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>
复制代码

3、按照查询嵌套处理

<!--(子查询)-->       <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="getStudent" column="id"/></resultMap>
<select id="getStudent" resultType="Student"> select * from mybatis.student where tid=#{tid};</select>
复制代码


小结


  • 关联 - association 【多对一】

  • 集合 - collection 【对多】

  • JavaType & ofType

  • JavaType 用来指定实体类中属性的类型

  • ofType 用来指定映射到 List 或者集合中的 pojo 类型,泛型中的约束类型


注意点:


  • 尽量保证 SQL 的可读性,尽量保证通俗易懂

  • 注意一对多、多对一中,属性名和字段问题!!

  • 如果问题不好排除,可以使用日志~ 建议 Log4j 【其实默认的也够用了】

  • 避免慢 SQL


面试:


  • Mysql 引擎

  • InnoDB 底层原理

  • 引擎

  • 索引优化!


@[toc]

12 动态 SQL

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


利用动态 SQL 这一特性可以摆脱这种痛苦。


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


  • if

  • choose (when,otherwise)

  • trim (where, set)

  • foreach

12.1 搭建环境

CREATE TABLE `blog`(  `id` VARCHAR(50) NOT NULL COMMENT '博客',  `title` VARCHAR(100) NOT NULL COMMENT '博客标题',  `author` VARCHAR(30) NOT NULL COMMENT '博客作者',  `create_time` DATETIME NOT NULL COMMENT '创建时间',  `views` INT(30) NOT NULL COMMENT'浏览器')ENGINE=INNODB DEFAULT CHARSET=utf8
复制代码


  • 创建一个基础工程

  • 导包

  • 编写配置文件

  • 编写实体类

  • 编写实体类对应的 Mapper 接口和 Mapper.xml 文件

12.2 IF

<!--parameterType 输入类型        resultType    返回结果集    --><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>
复制代码

12.3 choose (when,otherwise)

<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>
复制代码

12.4 trim (where, set)

<!-- where标签  会去除多余的 “AND” 或 “OR”,或 "where" --><select id="queryBlogIF" parameterType="map" resultType="blog">    select * from mybatis.blog    <where>        <if test="title != null">            and title = #{title}        </if>        <if test="author != null">            and author = #{author}        </if>    </where></select>
复制代码


<!-- set标签  会去除多余的 " 逗号",或 "set" --><update id="updateBlog" parameterType="map" >    update mybatis.blog    <set>        <if test="title != null">            title = #{title},        </if>        <if test="author != null">            author = #{author},        </if>    </set>    where id = #{id}</update>
复制代码


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


if where set choose when

12.5 SQL 片段

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


使用 SQL 标签抽取公共部分


<sql id="sql-if-title-author">    <if test="title != null">        title = #{title}    </if>    <if test="author != null">        and author = #{author}    </if></sql>
复制代码


在需要使用的地方使用 Include 标签引用即可


<!--parameterType 输入类型        resultType    返回结果集    --><select id="queryBlogIF" parameterType="map" resultType="blog">    select * from mybatis.blog    <where>        <include refid="sql-if-title-author"/>    </where></select>
复制代码


注意事项:


最好基于单表定义 SQL 片段!!sql 标签不要存在 where 标签 因为他是动态的

12.6 Foreach

select * from user where 1=1 and 
<foreach item="id" collection="ids" open="(" separator="or" close=")"> #{id}</foreach>
(id=1 or id=2 or id=3)
复制代码



相当于遍历一个数组


<!--        集合 select * from user where 1=1 and (id=1 or id=2 or id=3)        我们现在传递一个万能的map,这map可以存在一个集合!    collection:集合      item:集合里的数据--><select id="queryBlogForeach" parameterType="map" resultType="blog">    select * from mybatis.blog    <where>        <foreach item="id" collection="ids" open="and (" separator="or" close=")">            id=#{id}        </foreach>    </where></select>
复制代码


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


建议:


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

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2022.07.29 加入

还未添加个人简介

评论

发布
暂无评论
【SSM】Mybatis系列——多对一和一对多的处理、动态SQL_mybatis_胖虎不秃头_InfoQ写作社区