springboot +mybatis实现多表一对一查询
这篇文章并没有新加什么依赖。若你是新项目可以参考一下这篇文章:springboot整合mybatis实现单表增删改查
项目效果:
![](/assets/blank.gif)
一对一查询
首先展示页面效果和项目结构吧。这里是联合了数据库中的person表和idcard表。
person表:
idcard表:
最终效果:
项目结构:
先来解释一些名词含义:
一对一查询,就是指的是表关系,比如我这里的是学生表和学生卡表就是一对一的,一个学生只有一张学生卡,一张学生卡必然也对应着一个学生;
一对多:可以理解为一个母亲有多个孩子,或者一个部门有多个员工。一就是母亲或者部门,多就是孩子和员工;
多对多:可以理解为一个学生可以选择很多门课程,一门课程可以有很多个学生去选择。此时两者的关系就需要一个中间表来建立,比如说选课表。
字段名:数据库表中定义的每一列的名字。
属性名:定义在springboot中类中s定义的名字。如下图:
今天这里就介绍一下一对一查询,介绍两种方法。
第一种方法
pojo对象类
Person类
package com.example.csdn_release.pojo;import lombok.Data;import java.util.List;//可以省略getset方法和toString方法
@Data
public class Person {private int id;private int age;private String name;private Idcard idcardid;
}
Idcard类
package com.example.csdn_release.pojo;import lombok.Data;@Data
public class Idcard {private int id;private String stuid;private String classname;
}
dao层
还是从底层dao开始写。在PersonMapper中新增一个方法
//查询所有person信息和他们的学生卡信息
public List<Person> findAllPersonIdcardid();
mappers
继续写mappers文件夹中的PersonMapper.xml文件,这也是待会比价难懂的地方。这里先讲普通的方法,也是我觉得巨简单的方法。先贴代码在解释
<!-- 查询所有的idcardid,一对一查询 --><select id="findAllPersonIdcardid" resultMap="personIdcard">select person.* ,idcard.stuid,idcard.classnamefrom person,idcardwhere person.idcardid=idcard.id</select><resultMap id="personIdcard" type="com.example.csdn_release.pojo.Person"><id column="id" property="id"></id><result property="name" column="name"></result><result property="age" column="age"></result>
<!--person需要IDcard实体类子段映射到数据库 的多个字段-->
<!-- idcardid是与上面查询语句查询出来的列明对应,也就是对应于person表中发idcardid--><association property="idcardid" javaType="com.example.csdn_release.pojo.Idcard"><id property="id" column="idcardid"></id><result column="stuid" property="stuid"></result><result property="classname" column="classname"></result></association></resultMap>
select标签
这里select标签中的id就是对应于我们dao层中的新加的那个方法名,然后resultMap=“”就是对应于select标签下的那个resultMap标签的id名。这样就是得select查询标签与resultMap关联起来了。继续讲解这个SQL语句,因为是使用两表联查,所以我们这里就涉及了两个表中查询。person表中的idcardid就对应于idcard表中 的id。但是这可不是随便对应 的,必须得是idcard表中的主键才行。
resultMap标签
你可能会有疑问,为什么要有resultMap标签呢?不要可不可以呢?
如果sql查询到的字段与pojo中定义的类中的属性名不一致,则需要使用resultMap将字段名和属性名对应起来,进行手动配置封装,将结果映射到pojo中。这里我们就是person表中的属性不一致,因为它多了一个idcard属性。涉及了两个或者多个就需要resultMap了。所以resultMap中就需要包含person表中的所有字段和属性,还要加上idcard表中的字段和属性。person表中的就是常规的就OK。idcard表中的字段就需要使用association ,理解为集合的意思,在这个标签中写idcard表中的所有字段和属性就OK啦。然后这句话中的property就是对应于我在Person类中定义的属性名:private Idcard idcardid;
service层
PersonService接口类
新加查询方法。
// 级联查询查询所有人和校园卡信息public List<Person> findAllPersonAndIdcard2();
PersonServiceImpl接口实现类
就是在这里调用dao层中personMapper中的findAllPersonIdcardid就行啦
/*person表person表和idcard表一对一查询出来所有人的信息和校园卡情况*/@Overridepublic List<Person> findAllPersonAndIdcard() {return personMapper.findAllPersonIdcardid();}
controller层
@RequestMapping("personlist")
// model可以为html页面传递参数public String personList(Model model){// 传递参数,在这里调用service接口
// 使用一对一查询借口
//普通多表一对一查询model.addAttribute("personlist",personService.findAllPersonAndIdcard()); //model.addAttribute("personlist",personService.findAllPersonAndIdcard2());第二种方式级联查询接口
// 拦截到请求后将personlist.html的页面映射出来return "personlist.html";}
templates
新建一个personlist.html文件,与上面return返回的页面对应。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head><meta charset="UTF-8"><title>用户列表</title>
</head>
<body>
<!--一个基本的 html表格-->
<table border="1px" cellspacing="0px"><tr><th th:width="40px">id</th><th th:width="40px">年龄</th><th th:width="40px">姓名</th><th th:width="40px">学号</th><th th:width="150px">班级</th><th >删除</th><th>更新</th></tr><tr th:each="person:${personlist}"><td th:text="${person.id}"></td><td th:text="${person.age}"></td><td th:text="${person.name}"></td><td th:text="${person.idcardid.stuid}"></td><td th:text="${person.idcardid.classname}"></td><td><a th:href="@{deletepersonbyid(id=${person.id})}">删除用户</a> </td><td><a th:href="@{updatepersonbyid(id=${person.id},name=${person.name},age=${person.age})}">更新用户</a> </td></tr>
</table>
</body>
</html>
第一种方式就讲完了,第二种方式除了mapper映射的xml文件有些不同。
第二种方式
pojo中新建一个Idcard类,最上面我已经给了粗来了。往上面翻一翻,
dao层
新建一个IDcardMapper接口类
代码:
这里就是传入一个id来查询idcard的信息。有些人可能就会问,我们不是要查询表中所有的信息吗,往上面要传入id呀,那不是只能查询一个人的 信息吗?这也是我上课的时候有点不理解的地方,导致最后跟着老师的节奏把我的上课那个项目给写崩了,一直没有解决是哪里出错,问了老师也没有解决。但是还好我一直坚持在写博客,我写博客这个项目是我重写上课老师的那个项目的,所以我直接就换了这个项目了。我仔细回想一遍好像和我现在写的步骤完全一致呀。思路也很清晰为什么就崩了呢。不理解。继续写这个项目把。放心!!!!!这个项目是跑得起来的,我不会把错误的代码放到我的博客上面滴!!!!!好吧,待会来个视频演示算了~~~~~~~~
package com.example.csdn_release.dao;
import com.example.csdn_release.pojo.Idcard;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface IDcardMapper {Idcard findIdcardById(Integer id);//级联查询第一步
}
mappers中新建IdcardMapper.xml文件
就是为了对应上面那个IdcardMapper接口类。执行SQL语句
<?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.csdn_release.dao.IDcardMapper"><select id="findIdcardById"parameterType="Integer"resultType="com.example.csdn_release.pojo.Idcard">select * from idcard where id=#{id}</select>
</mapper>
PersonMapper.xml
在PersonMapper.xml中新加一个级联查询的select标签,并为这个标签设置一个resultMap.xml 直接放在第一种方法的resultMap下就可以了。方便对比
<!-- 级联查询--><select id="findAllPersonIdcardid2" resultMap="personIdcard2">select * from person</select><resultMap id="personIdcard2" type="com.example.csdn_release.pojo.Person"><id column="id" property="id"></id><result property="name" column="name"></result><result property="age" column="age"></result><!--person需要IDcard实体类子段映射到数据库 的多个字段--><!-- idcardid是与上面查询语句查询出来的列明对应,也就是对应于person表中发idcardid,select查询语句将查询出来的结果映射到javaType中去column中的idcardid是通过使用这个resultMap的select中查询得到的idcardid。然后将查询到的IDcardid作为参数传到这个select语句中去查询作为参数传到select语句中--><association property="idcardid"javaType="com.example.csdn_release.pojo.Idcard"column="idcardid"select="com.example.csdn_release.dao.IDcardMapper.findIdcardById"></association></resultMap>
在这里首先可以发现select标签中的SQL语句变了。因为级联查询是分为好几步的,我们这里是先查询出所有的person表信息。然后我们这里为它加了一个id为personIdcard2的resultMap。idcardid是与上面查询语句查询出来的列明对应, 也就是对应于person表中发idcardid,select查询语句将查询出来的结果映射到javaType中去column中的idcardid是通过使用这个resultMap的select中查询得到的idcardid。然后将查询到的IDcardid作为参数传到这个select语句中去查询作为参数传到select语句中
service层
personService接口类新加一个方法
这里我为了让你们更加清楚我就多写一个接口,就不用第一个方法的接口了,免得你们混淆
// 级联查询查询所有人public List<Person> findAllPersonAndIdcard2();
实现类
// 级联查询查询所有的person表与IDcard表的关联@Overridepublic List<Person> findAllPersonAndIdcard2() {return personMapper.findAllPersonIdcardid2();}
Controll层
在PersonControl中直接修改里面的一行代码就行。就是改了一个调用方法。
不要新加,就是在原有的里面修改
@RequestMapping("personlist")
// model可以为html页面传递参数public String personList(Model model){// 传递参数,在这里调用service接口
// 使用一对一查询借口
//普通多表一对一查询//model.addAttribute("personlist",personService.findAllPersonAndIdcard()); //第二种方式级联查询接口model.addAttribute("personlist",personService.findAllPersonAndIdcard2());
// 拦截到请求后将personlist.html的页面映射出来return "personlist.html";}
增加
IDcardMapper接口类
新加一个方法
int addIdcard(Idcard idcard);
对应的xml问件
<!-- useGeneratedKeys:增加的数据主键返回,又叫主键回填,因为我们这里并没有新加id值它是由数据库设置的id自增长的,所以我们增加一条数据后可以拿到这个idkeyProperty:返回的主键复制给idcard的属性--><insert id="addIdcard"parameterType="com.example.csdn_release.pojo.Idcard"useGeneratedKeys="true" keyProperty="id">insert into idcard(stuid,classname) values (#{stuid},#{classname})</insert>
接口实现类
public int addPerson(Person person) {// 第一步:先增加IDcard表数据int result=iDcardMapper.addIdcard(person.getIdcardid());
// 第二部:再增加Person表数据int result2=personMapper.addPerson(person);if(result2>0&&result>0){return result2;}//添加失败return 0;}
controll层
@RequestMapping("addperson")public String addperson(){return "addperson.html";}@RequestMapping("addpersoncommit")public String addpersoncommit(Person person){personService.addPerson(person);return "redirect:/personlist";}
删除
删除主要是需要同时删除两个表中的数据。这里就快一点了。
personList.html
在这个页面中主要是在删除的 时候同时向服务器传递两个主键就OK了。两种拼接法:
//第一种<td><a th:href="@{'/deletepersonbyid?id='+${person.id}+'&cardid='+${person.idcardid.id}}">删除用户</a> </td>//第二种<td><a th:href="@{'deletepersonbyid(id=${person.id},cardid=${person.idcardid.id})}">删除用户</a> </td>
dao层两个删除方法
删除学生卡信息:
public Integer deleteIdcardById(Integer id);
对应的xml文件:
<delete id="deleteIdcardById" parameterType="Integer">delete from idcard where id=#{id}</delete>
删除学生信息:
public Integer deletePersonById(Integer id);
对应的xml文件:
<delete id="deletePersonById" parameterType="Integer">delete from person where id=#{id}</delete>
service 层
@Overridepublic int deletePersonById(Integer id,Integer cardid) {int result=personMapper.deletePersonById(id);int result2=iDcardMapper.deleteIdcardById(cardid);if(result2>0&&result>0){return result2;}return 0;}
controller层
@RequestMapping("deletepersonbyid")public String deletepersonbyid(int id,int cardid){personService.deletePersonById(id,cardid);return "redirect:/personlist";}
然后其他的就不用变,直接运行就OK了。如果有什么问题欢迎评论区留言或者私信哟
springboot +mybatis实现多表一对一查询相关推荐
- springboot+mybatis+mysql 多表联合查询
###springboot+mybatis+mysql 多表查询 这里有两张表 用户表和用户信息表user.info 两个实体类展示他们一对一的关系 通过springboot注解的方式实现多表联合查询 ...
- 利用SSM(springmvc+spring+mybatis)实现多表联合查询
最近在做在eclipse + maven搭建SSM框架下做一个简单的后台管理系统,因为是第一次搭建SSM项目,在mybatis进行多表连接查询的时候遇到问题,不知道如何进行处理?在网上搜了一下解决方法 ...
- 解决Springboot+JPA中多表关联查询会查询多次的问题(n+1查询问题)
解决Springboot+JPA中多表关联查询会查询多次的问题(n+1查询问题) 参考文章: (1)解决Springboot+JPA中多表关联查询会查询多次的问题(n+1查询问题) (2)https: ...
- MyBatis实现中间表关联查询
MyBatis实现中间表关联查询 通常构建数据多对多模型的关系时,我们需要再建立一张中间表来关联另外两张表. 下面介绍一下,怎么用MyBatis来实现中间表关联查询并封装到实体类对象中. 现在有三张表 ...
- Mybatis的多表关联查询(多对多)
Mybatis的多表关联查询(多对多) 项目目录结构 实现 Role 到 User 多对多 业务要求 用户与角色的关系模型 编写角色实体类 编写 Role 持久层接口 实现的 SQL 语句 编写映射文 ...
- asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
本文我们将继续分享介绍Spring Boot在整合Mybatis开发企业级应用时其他典型的业务场景,即Mybatis是如何实现多表关联查询时将查询结果集与对象进行映射的,主要的内容包含"一对 ...
- mybatis教程--映射之一对一查询
一对一查询 这里我们是在用户表,订单表,订单详情表,商品表的基础上进行讲解的.下面我也会把这四张表的po类列出来. 1.1 需求 查询订单信息关联查询用户信息 1.2 sql语句 查询语句: 先确定主 ...
- order by 子查询_【框架】118:mybatis之多表高级查询
今天是刘小爱自学Java的第118天. 感谢你的观看,谢谢你. 学习内容安排如下: 补充说明知识点:resultMap,sql片段. mybatis中的高级查询,即多表关联查询. 查询主要分为:一对一 ...
- MyBatis框架 多表联合查询实现
三种方式: ①业务装配 对两个表编写单表查询语句,在业务层(Serivce)把查询的两个结果进行关联 ②使用Auto Mapping特性 在实现两表联合查询时通过别名完成映射,使用Maybatis的& ...
最新文章
- 【转】webgame前台开发总结--虽然是10年的文章,但是也有参考价值
- 宏任务和微任务执行顺序_确保任务的执行顺序
- Flink JDBC Connector:Flink 与数据库集成最佳实践
- perl多进程实战之一
- 通过filebeat、logstash、rsyslog采集nginx日志的几种方式
- CrackMe022
- manjaro linux 使用Xorg显示服务器
- 搜狗快速排名软件到底哪家更强大?
- 基于C++实现校园卡管理系统
- 啊哈算法2伟大思维闪耀时_「坐在马桶上看算法」算法6:只有五行的Floyd最短路算法...
- U盘启动盘制作,金士顿2GU盘量产工…
- linux如何安装压缩软件,linux之安装软件,压缩解压文件
- tplink怎么进去_如何进入路由器设置界面 如何登陆无线路由器
- 自从自己搭建了这套精选壁纸聊天背景的微信小程序,我的手机背景图再都没重复过
- 通过西联快汇收取Google Adsense收入的详细步骤
- 新版UI聚合支付系统四方系统源码+修复漏洞完美版
- Sublime Text 崇高文本 ----最性感的编辑器(程序员必备)
- 沈剑架构师之路的分享-总结
- kill -15 与kill -9的区别
- 5种顶级逻辑思维训练法:1min 轻松上手,工作学习都能用
热门文章
- 讯飞智能录音笔SR502内存升级,实力更强大
- Qt - 从零到壹的 打地鼠 游戏
- 汽车厂商 API数据接口
- [总结] 全部笔记博文目录总结(持续更新...)
- matlab画渐变色三维柱状图
- python批量修改文件扩展名
- Web工程师和设计师必须要知道的 iOS 8的十个变化
- 机器学习研究项目--以机器视觉工程师的视角(MLP篇)
- 计算机应用中dss是,基于数据仓库的决策支持系统(DSS)-计算机应用专业论文.docx...
- DSS部署-7、配置Python