狂神说MyBatis学习笔记: MyBatis中一对多和多对一处理

您所在的位置:网站首页 mybatis复杂查询 狂神说MyBatis学习笔记: MyBatis中一对多和多对一处理

狂神说MyBatis学习笔记: MyBatis中一对多和多对一处理

2023-10-13 17:41| 来源: 网络整理| 查看: 265

文章目录 前言一、多对一关系的查询数据表:实体类:对应的mapper文件:方法一: 嵌套select查询(按照查询进行嵌套处理)方法二: 按照结果进行嵌套处理 二、一对多关系的查询方式一:按照结果进行嵌套处理方式二:按照查询进行嵌套处理查询结果 总结

前言

笔者在学习MyBatis课程中,听了很多慕课,最终发现还是狂神老师讲的最好。本篇是根据狂神老师的 狂神说MyBatis05:一对多和多对一处理 学习完后的整理笔记,结合了狂神老师的讲解和自己的理解,旨在弄通这个知识点。

如果本文中的一些基本概念不了解,比如resultMap,collection,和association这些字段看不懂,建议先去科普一下MyBatis的基本配置: 简单讲解MyBatis中的resultMap,collection,association

一、多对一关系的查询 数据表:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存失败,源站可能有防盗链机制,建议将图片保存下来直接上传上传(im4joVN1F1GS-1605707855087)(C:\Users\WZR11\AppData\Roaming\Typora\typora-user-images\image-20201118200332027.png)(C:\Users\WZR11\AppData\Roaming\Typora\typora-user-images\image-20201118200332027.png)]

实体类:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yHxJvWwG-1605707855094)(C:\Users\WZR11\AppData\Roaming\Typora\typora-user-images\image-20201118200402937.png)]

其中 学生和教师是多对一关系, 所以在学生表中有一个外键,指向教师表的主键

虽然在数据表中,外键是int型的(tid), 只负责指向教师表的主键id. 但是在实体类中没有这个int型的外键(tid), 取而代之的直接是一个教师类型的实体类.

这里很蒙是不是? 原因就在于, 从需求角度考虑, 我们想要查出来的结果是下图这个东西:

在这里插入图片描述

现在是不是明白多了? 实体类不一定要完全和数据库中的字段相对应,它是要为展示数据负责的(最终你想要查出来什么结果,实体类就是什么样子的)

对应的mapper文件: 方法一: 嵌套select查询(按照查询进行嵌套处理) select * from student select * from teacher where id = #{tid}

观察该方法,为什么叫嵌套select? 因为你看下面这一行有一个select字段:

该select字段直接对应了最下面那个id为getTeacher的标签. 这其实是嵌套了另一个标签的操作. 注意看该标签里面的sql语句:

select * from teacher where id = #{tid}

id = #{tid} , 这个tid就是前面association标签里面 column=“tid” 里传过来的tid。

方法二: 按照结果进行嵌套处理 select s.id sid, s.name sname , t.name tname from student s,teacher t where s.tid = t.id

先讲一下sql语句:

select s.id sid, s.name sname , t.name tname from student s,teacher t where s.tid = t.id

s是student的别名(之前有配),看不懂的话可以直接写student。t就是teacher,看不懂的话换成teacher也行,不用纠结这里,反正s和t就是代表学生表和老师表的意思

s.id后面跟的sid, 其实是在sql里起了一个别名. 后面的sname和tname也是sql语法中的别名

所以, 后面配置resultMap时的column属性, 本来对应的虽说是数据库字段, 但是由于数据库字段都有别名了, 也应该配置别名的形式.

看下面的association代码:

这里是不是看不懂? 别急, 看下面最终查询结果是个什么东西, 你就知道结果集映射是配的啥了

在这里插入图片描述

上图就是查询的结果, 其实就是Student的pojo实体类中的三个字段。

这次再来看前面的结果集映射代码,id和name字段都配好了,剩下的就是teacher字段。

按理说这里需要配置teacher的id和name。但是上面的代码中只配置了name属性,

因为我们的需求根本不需要查teacher的id属性,只需要查teacher->name(select s.id sid, s.name sname , t.name tname)。括号里也就是我们的sql语句,从语句中看需求只需要查出来 student的id属性, student的name属性 和 teacher的name属性这三个即可。

这也解释了上图为啥id全都是0(本来秦老师的id是1),因为我们根本就没配id属性。

二、一对多关系的查询

问题来了,前面已经说了多对一 ,那这里为啥要再重新学一遍一对多呢?

看下图,下图是多对一查出来的结果,学生是多的一方,最后查出来的是学生的信息:

在这里插入图片描述

但是如果我们需求是:以老师为主体,查老师的信息呢?

在这里插入图片描述

想实现上面的需求,首先需要改动实体类:

在这里插入图片描述

最终查出来的信息是长这个样的:

在这里插入图片描述

(注意,这里的students是一个List,泛型是)

废话不多说,下面开始介绍如何查询:

其实和前面的多对一查询的两种方式大同小异,都是按照结果进行嵌套处理 或者 按照查询进行嵌套处理

方式一:按照结果进行嵌套处理 TeacherMapper接口编写方法 //获取指定老师,及老师下的所有学生 public Teacher getTeacher(int id); 编写接口对应的Mapper配置文件 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=#{id}

解释一下,sql语句的最后一行 where s.tid = t.id and t.id=#{id} 里面的#{id},就是接口传进来的参数public Teacher getTeacher(int id);

方式二:按照查询进行嵌套处理 TeacherMapper接口编写方法 //获取指定老师,及老师下的所有学生 public Teacher getTeacher2(int id); 编写接口对应的Mapper配置文件 select * from teacher where id = #{id} select * from student where tid = #{id}

注意看这里的javaType字段,写的是ArrayList!因为传进去的返回值类型的确是List类型,而Student类只是List的泛型,泛型要用ofType来传递。

不要小看这里的细节,出错的往往是这些细节!

查询结果

不管是用上面的哪种方法,结果都是长得像下图这个样的,即获取指定老师下的所有学生及老师的信息:

在这里插入图片描述

总结

这里介绍了两种方法查询:

按照查询进行嵌套处理 和 按照结果进行嵌套处理

按照查询进行嵌套处理就像SQL中的子查询

按照结果进行嵌套处理就像SQL中的联表查询

按照结果进行嵌套处理往往要写复杂的SQL语句,按照查询进行嵌套处理往往要进行复杂的映射配置。

笔者比较喜欢按照结果进行嵌套处理,因为配置resultMap的映射本质就是为了解决属性名和字段不一致的问题,把sql语句写完整了,可以得出多种映射的结果,只需要照着配置就完了。况且掌握复杂查询的SQL语句本身就是一个程序猿的基本功。

最后还差一个多对多关系的处理的总结,日后再更新。

这个知识点如果学不会,完全就是SQL基础没打好的问题 ,建议重新学一下数据库基础。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3