SpringBoot实战:多表联查
1. 保存和更新公寓信息
请求数据的结构
@Schema(description = "公寓信息")
@Data
public class ApartmentSubmitVo extends ApartmentInfo {@Schema(description="公寓配套id")private List<Long> facilityInfoIds;@Schema(description="公寓标签id")private List<Long> labelIds;@Schema(description="公寓杂费值id")private List<Long> feeValueIds;@Schema(description="公寓图片id")private List<GraphVo> graphVoList;}
Controller层
@Operation(summary = "保存或更新公寓信息")@PostMapping("saveOrUpdate")public Result saveOrUpdate(@RequestBody ApartmentSubmitVo apartmentSubmitVo) {apartmentInfoService.saveOrUpdateApartment(apartmentSubmitVo);return Result.ok();}
Service层
void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo);
/*** 保存或更新公寓信息** @param apartmentSubmitVo 公寓信息提交对象* 若传入公寓ID为空,则执行插入操作;若不为空,则执行更新操作* 更新操作时会先删除原有配套、杂费、标签和图片信息,再插入新的信息*/@Overridepublic void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {//保存或修改公寓信息://1.判断该参数id是否为空,为空:插入的新数据 不为空:修改数据boolean isUpdate = apartmentSubmitVo.getId() != null;//2.调用父类保存或修改方法,将公寓基本信息进行保存super.saveOrUpdate(apartmentSubmitVo);if (isUpdate) {//修改数据:直接将所有原数据删除后重新插入//1.删除配套LambdaQueryWrapper<ApartmentFacility> facilityLambdaQueryWrapper = new LambdaQueryWrapper<>();facilityLambdaQueryWrapper.eq(ApartmentFacility::getApartmentId, apartmentSubmitVo.getId());facilityService.remove(facilityLambdaQueryWrapper);//2.删除杂费LambdaQueryWrapper<ApartmentFeeValue> feeValueLambdaQueryWrapper = new LambdaQueryWrapper<>();feeValueLambdaQueryWrapper.eq(ApartmentFeeValue::getFeeValueId, apartmentSubmitVo.getId());feeValueService.remove(feeValueLambdaQueryWrapper);//3.删除标签LambdaQueryWrapper<ApartmentLabel> labelLambdaQueryWrapper = new LambdaQueryWrapper<>();labelLambdaQueryWrapper.eq(ApartmentLabel::getLabelId, apartmentSubmitVo.getId());labelService.remove(labelLambdaQueryWrapper);//4.删除图片LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();graphInfoLambdaQueryWrapper.eq(GraphInfo::getId, apartmentSubmitVo.getId());graphInfoService.remove(graphInfoLambdaQueryWrapper);}//1.插入配套List<Long> facilityInfoIdsList = apartmentSubmitVo.getFacilityInfoIds();if (!CollectionUtils.isEmpty(facilityInfoIdsList)) {ArrayList<ApartmentFacility> facilityArrayList = new ArrayList<>();for (Long facilityId : facilityInfoIdsList) {ApartmentFacility apartmentFacility = ApartmentFacility.builder().build();apartmentFacility.setFacilityId(facilityId);apartmentFacility.setApartmentId(apartmentSubmitVo.getId());facilityArrayList.add(apartmentFacility);}facilityService.saveBatch(facilityArrayList);}//2.插入杂费List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();if (!CollectionUtils.isEmpty(feeValueIds)) {ArrayList<ApartmentFeeValue> apartmentFeeValueList = new ArrayList<>();for (Long feeValueId : feeValueIds) {ApartmentFeeValue apartmentFeeValue = ApartmentFeeValue.builder().build();apartmentFeeValue.setApartmentId(apartmentSubmitVo.getId());apartmentFeeValue.setFeeValueId(feeValueId);apartmentFeeValueList.add(apartmentFeeValue);}feeValueService.saveBatch(apartmentFeeValueList);}//3.插入标签List<Long> labelIds = apartmentSubmitVo.getLabelIds();if (!CollectionUtils.isEmpty(labelIds)) {ArrayList<ApartmentLabel> apartmentLabelArrayList = new ArrayList<>();for (Long labelId : labelIds) {ApartmentLabel apartmentLabel = ApartmentLabel.builder().build();apartmentLabel.setApartmentId(apartmentSubmitVo.getId());apartmentLabel.setLabelId(labelId);apartmentLabelArrayList.add(apartmentLabel);}labelService.saveBatch(apartmentLabelArrayList);}//4.插入图片List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();if (!CollectionUtils.isEmpty(graphVoList)) {ArrayList<GraphInfo> graphInfos = new ArrayList<>();for (GraphVo graphVo : graphVoList) {GraphInfo graphInfo = new GraphInfo();graphInfo.setItemType(ItemType.APARTMENT);graphInfo.setItemId(apartmentSubmitVo.getId());graphInfo.setName(graphVo.getName());graphInfo.setUrl(graphVo.getUrl());graphInfos.add(graphInfo);}graphInfoService.saveBatch(graphInfos);}}
2. 根据条件分页查询
请求数据结构
@Data
@Schema(description = "公寓查询实体")
public class ApartmentQueryVo {@Schema(description = "省份id")private Long provinceId;@Schema(description = "城市id")private Long cityId;@Schema(description = "区域id")private Long districtId;
}
响应数据结构
@Data
@Schema(description = "后台管理系统公寓列表实体")
public class ApartmentItemVo extends ApartmentInfo {@Schema(description = "房间总数")private Long totalRoomCount;@Schema(description = "空闲房间数")private Long freeRoomCount;}
Controller层
@Operation(summary = "根据条件分页查询公寓列表")@GetMapping("pageItem")public Result<IPage<ApartmentItemVo>> pageItem(@RequestParam long current, @RequestParam long size, ApartmentQueryVo queryVo) {Page<ApartmentItemVo> page = new Page<>(current, size);IPage<ApartmentItemVo> result = apartmentInfoService.pageItem(page, queryVo);return Result.ok(result);}
Service层
IPage<ApartmentItemVo> pageItem(Page<ApartmentItemVo> page, ApartmentQueryVo queryVo);
@Overridepublic IPage<ApartmentItemVo> pageItem(Page<ApartmentItemVo> page, ApartmentQueryVo queryVo) {return apartmentInfoMapper.pageItem(page, queryVo);}
Mapper层
IPage<ApartmentItemVo> pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo);
多表联查大sql
<select id="pageItem" resultType="com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo">select ai.id,ai.name,ai.introduction,ai.district_id,ai.district_name,ai.city_id,ai.city_name,ai.province_id,ai.province_name,ai.address_detail,ai.latitude,ai.longitude,ai.phone,ai.is_release,ifnull(tc.cnt, 0) total_room_count,ifnull(tc.cnt, 0) - ifnull(cc.cnt, 0) free_room_countfrom (select id,name,introduction,district_id,district_name,city_id,city_name,province_id,province_name,address_detail,latitude,longitude,phone,is_releasefrom apartment_info<where>is_deleted=0<if test="queryVo.provinceId != null">and province_id=#{queryVo.provinceId}</if><if test="queryVo.cityId != null">and city_id=#{queryVo.cityId}</if><if test="queryVo.districtId != null">and district_id=#{queryVo.districtId}</if></where>) aileft join(select apartment_id,count(*) cntfrom room_infowhere is_deleted = 0and is_release = 1group by apartment_id) tcon ai.id = tc.apartment_idleft join(select apartment_id,count(*) cntfrom lease_agreementwhere is_deleted = 0and status in (2, 5)group by apartment_id) ccon ai.id = cc.apartment_id</select>
knife4j调整传递参数
默认情况下Knife4j为该接口生成的接口文档如下图所示,其中的queryVo参数不方便调试

可在application.yml文件中增加如下配置,将queryVo做打平处理
springdoc:default-flat-param-object: true

3. 根据ID获取公寓详细信息
响应数据
@Schema(description = "公寓信息")
@Data
public class ApartmentDetailVo extends ApartmentInfo {@Schema(description = "图片列表")private List<GraphVo> graphVoList;@Schema(description = "标签列表")private List<LabelInfo> labelInfoList;@Schema(description = "配套列表")private List<FacilityInfo> facilityInfoList;@Schema(description = "杂费列表")private List<FeeValueVo> feeValueVoList;
}
Controller层
@Operation(summary = "根据ID获取公寓详细信息")@GetMapping("getDetailById")public Result<ApartmentDetailVo> getDetailById(@RequestParam Long id) {ApartmentDetailVo apartmentDetailVo = apartmentInfoService.getDetailById(id);return Result.ok(apartmentDetailVo);}
Service层
ApartmentDetailVo getDetailById(Long id);
@Overridepublic ApartmentDetailVo getDetailById(Long id) {//1.查询公寓基本信息ApartmentInfo apartmentInfo = apartmentInfoMapper.selectById(id);//2.查询图片列表List<GraphVo> graphVoList = graphInfoMapper.selectGraphVoList(id, ItemType.APARTMENT);//3.查询标签列表List<LabelInfo> labelInfoList = labelInfoMapper.selectLabelInfoList(id); //通过公寓id查询出所有标签id,在通过标签id查出所有标签信息//4.查询配套列表List<FacilityInfo> facilityInfoList = facilityInfoMapper.selectFacilityInfoList(id); //通过公寓id查询出所有配套id,在通过配套id查出所有配套信息//5.查询杂费列表List<FeeValueVo> feeValueList = feeValueMapper.selectFeeValueList(id); //通过公寓id查询出所有杂费值id,在通过杂费值id查出所有杂费以及杂费名称id,再通过杂费名称id查出杂费名//6.组装结果ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);apartmentDetailVo.setGraphVoList(graphVoList);apartmentDetailVo.setLabelInfoList(labelInfoList);apartmentDetailVo.setFacilityInfoList(facilityInfoList);apartmentDetailVo.setFeeValueVoList(feeValueList);return apartmentDetailVo;}
Mapper。。。
4. 根据ID删除公寓信息
@Operation(summary = "根据id删除公寓信息")@DeleteMapping("removeById")public Result removeById(@RequestParam Long id) {apartmentInfoService.removeApartmentById(id);return Result.ok();}
相关文章:
SpringBoot实战:多表联查
1. 保存和更新公寓信息 请求数据的结构 Schema(description "公寓信息") Data public class ApartmentSubmitVo extends ApartmentInfo {Schema(description"公寓配套id")private List<Long> facilityInfoIds;Schema(description"公寓标签i…...
解决mysql,Navicat for MySQL,IntelliJ IDEA之间中文乱码
使用软件版本 jdk-8u171-windows-x64 ideaIU-2021.1.3 mysql-essential-5.0.87-win32 navicat8_mysql_cs 这个问题我调试了好久,网上的方法基本上都试过了,终于是解决了。 三个地方结果都不一样。 方法一 首先大家可以尝试下面这种方法:…...
虚拟环境操作
1、对虚拟环境的操作 查看虚拟环境列表 conda env list 创建虚拟环境 conda create -n 虚拟环境名称 python3.x 激活虚拟环境 conda activate 虚拟环境名称 退出虚拟环境 conda deactivate 删除虚拟环境 conda remove -n 虚拟环境名称 all 2、对虚拟环境下的包的操作…...
企业网三层架构
企业网三层架构:是一种层次化模型设计,旨在将复杂的网络设计分成三个层次,每个层次都着重于某些特定的功能,以提高效率和稳定性。 企业网三层架构层次: 接入层:使终端设备接入到网络中来,提供…...
node.js的安装及学习(node/nvm/npm的区别)
一、什么是node、nvm和npm 1.Node.js node.js 一种Javascript编程语言的运行环境,能够使得javascript能够脱离浏览器运行。以前js只能在浏览器(也就是客户端)上运行,node.js将浏览器中的javascript运行环境进行封装的,…...
性能优化篇:用WebSocket替代传统的http轮循
当我还是初级菜鸟时,我只会写定时器定时调用接口,发起http请求,定时轮训请求接口,返回最新数据,定时器开启的多了还会引起页面卡顿的性能问题,虽然及时销了但还是会影响流畅问题。然后技术leader一声令下说改成websoket的请求方式,为什么这么做呢?下面来谈谈WebSocket相…...
virtualbox的ubuntu默认ipv4地址为10.0.2.15的修改以及xshell和xftp的连接
virtualbox安装Ubuntu后,默认的地址为10.0.2.15 我们查看virtualbox的设置发现是NAT 学过计算机网络的应该了解NAT技术,为了安全以及缓解ip使用,我们留了部分私有ip地址。 私有IP地址网段如下: A类:1个A类网段&…...
Codeforces Round 957 (Div. 3)(A~D题)
A. Only Pluses 思路: 优先增加最小的数,它们的乘积会是最优,假如只有两个数a和b,b>a,那么a 1,就增加一份b。如果b 1,只能增加1份a。因为 b > a,所以增加小的数是最优的。 代码: #include<bi…...
fedora 40 安装拼音输入法
仅做参考,一般主流linux版本在安装完成后,都会自带中文输入法。而需要配置中文输入法的小众发行版往往软件仓库自带的依赖不全。 1,sudo dnf install ibus 2,sudo dnf install im-chooser 3,sudo dnf install ibus-libpinyin 4,在终端输入im-choose…...
Chromium CI/CD 之Jenkins实用指南2024-如何创建新节点(三)
1. 前言 在前一篇《Jenkins实用指南2024-系统基本配置(二)》中,我们详细介绍了如何对Jenkins进行基本配置,包括系统设置、安全配置、插件管理以及创建第一个Job。通过这些配置,您的Jenkins环境已经具备了基本的功能和…...
Git代码管理工具 — 3 Git基本操作指令详解
目录 1 获取本地仓库 2 基础操作指令 2.1 基础操作指令框架 2.2 git status查看修改的状态 2.3 git add添加工作区到暂存区 2.4 提交暂存区到本地仓库 2.5 git log查看提交日志 2.6 git reflog查看已经删除的记录 2.7 git reset版本回退 2.8 添加文件至忽略列表 1 获…...
Linux——多线程(五)
1.线程池 1.1初期框架 thread.hpp #include<iostream> #include <string> #include <unistd.h> #include <functional> #include <pthread.h>namespace ThreadModule {using func_t std::function<void()>;class Thread{public:void E…...
张量分解(4)——SVD奇异值分解
🍅 写在前面 👨🎓 博主介绍:大家好,这里是hyk写算法了吗,一枚致力于学习算法和人工智能领域的小菜鸟。 🔎个人主页:主页链接(欢迎各位大佬光临指导) ⭐️近…...
第三方配件也能适配苹果了,iOS 18与iPadOS 18将支持快速配对
苹果公司以其对用户体验的不懈追求和对创新技术的不断探索而闻名。随着iOS 18和iPadOS 18的发布,苹果再次证明了其在移动操作系统领域的领先地位。 最新系统版本中的一项引人注目的功能,便是对蓝牙和Wi-Fi配件的配对方式进行了重大改进,不仅…...
Docker 部署 Nginx 并在容器内配置申请免费 SSL 证书
文章目录 dockerdocker-compose.yml申请免费 SSL 证书请求头参数带下划线 docker https://hub.docker.com/_/nginx docker pull nginx:1.27注: 国内网络原因无法下载镜像,nginx 镜像文件下载链接 https://pan.baidu.com/s/1O35cPbx6AHWUJL1v5-REzA?pw…...
模型评估与选择
2.1 经验误差与过拟合 错误率(error rate): 分类错误的样本数占样本总数的比例 精度(accuracy):1- 错误率 训练误差 / 经验误差:在训练集上的误差 泛化误差:在新样本上的误差 过…...
有必要把共享服务器升级到VPS吗?
根据自己的需求来选择是否升级,虚拟专用服务器 (VPS) 是一种托管解决方案,它以低得多的成本提供专用服务器的大部分功能。使用 VPS,您的虚拟服务器将与在其上运行的其他虚拟服务器共享硬件服务器的资源。但是,与传统的共享托管&am…...
LLM代理应用实战:构建Plotly数据可视化代理
如果你尝试过像ChatGPT这样的LLM,就会知道它们几乎可以为任何语言或包生成代码。但是仅仅依靠LLM是有局限的。对于数据可视化的问题我们需要提供一下的内容 描述数据:模型本身并不知道数据集的细节,比如列名和行细节。手动提供这些信息可能很麻烦&#…...
大模型系列3--pytorch dataloader的原理
pytorch dataloader运行原理 1. 背景2. 环境搭建2.1. 安装WSL & vscode2.2. 安装conda & pytorch_gpu环境 & pytorch 2.112.3 命令行验证python环境2.4. vscode启用pytorch_cpu虚拟环境 3. 调试工具3.1. vscode 断点调试3.2. py-spy代码栈探测3.3. gdb attach3.4. …...
SQLServer 如何设置端口
在SQL Server中,可以通过以下步骤设置端口: 打开SQL Server配置管理器。可以在开始菜单中搜索“SQL Server配置管理器”来找到它。 在左侧导航窗格中,展开“SQL Server网络配置”节点。 选择你要配置的实例,如“SQL Server Netw…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
