3.点位管理改造-列表查询——帝可得管理系统

news/2024/12/21 22:54:58/

目录

  • 前言
  • 一、与页面原型差距
    • 1.现在:
    • 2.目标:
    • 3. 存在问题:
  • 二、修改
    • 1.重新设计SQL语句
    • 2.修改mapper层,使用Mybatis中的嵌套查询
    • 3.修改service层
    • 4. 修改controller层
    • 5.前端修改
    • 6.补充区域查看详情
    • 7.数据完整性

前言

提示:本篇目的是将点位管理中所在区域和合作商展示的ID改为对应的名称

一、与页面原型差距

1.现在:

在这里插入图片描述
点位管理的响应字段

{"total": 3,"rows": [{"createBy": null,"createTime": "2024-07-03 10:26:05","updateBy": null,"updateTime": "2024-07-03 10:26:05","remark": null,"id": 1,"nodeName": "三里屯点位","address": "北京市朝阳区三里屯路","businessType": 1,"regionId": 1,"partnerId": 1}...],"code": 200,"msg": "查询成功"
}

2.目标:

在这里插入图片描述
要求响应 返回的类型
在这里插入图片描述

3. 存在问题:

所在区域和合作商ID展示的都是ID,而不是名称;同时合作商ID应改为合作商
现阶段后端返回字段和目标字段对比,发现缺少region和partner信息

二、修改

1.重新设计SQL语句

-- 查询并显示点位表所有的字段信息,同时显示每个点位的设备数量
SELECTn.id,n.node_name,n.address,n.business_type,n.region_id,n.partner_id,n.create_time,n.update_time,n.create_by,n.update_by,n.remark,COUNT(v.id) AS vm_count
FROMtb_node n
LEFT JOINtb_vending_machine v ON n.id = v.node_id
GROUP BYn.id;-- 根据区域id查询区域信息
select * from tb_region where id=1;
-- 根据合作商id查询合作商信息
select * from tb_partner where id=1;

解释:上述第一条SQL查询了每个点位下的设备数量;后两条分别查询指定ID后,所对应的区域和合作商的全部信息。

2.修改mapper层,使用Mybatis中的嵌套查询

NodeVo:定义了返回给前端的字段。

java">@Data
public class NodeVo extends Node {// 设备数量private int vmCount;// 区域private Region region;// 合作商private Partner partner;
}

NodeMapper.java

/*** 查询点位管理列表* @param node* @return NodeVo集合*/
public List<NodeVo> selectNodeVoList(Node node);

NodeMapper.xml

  <!-- 返回结果:NodeVo  -->
<resultMap type="NodeVo" id="NodeVoResult"><!-- 从select中获取查询结果后,将column(数据库字段)与property(Java类字段)一一对应 --><result property="id"    column="id"    /><result property="nodeName"    column="node_name"    /><result property="address"    column="address"    /><result property="businessType"    column="business_type"    /><result property="regionId"    column="region_id"    /><result property="partnerId"    column="partner_id"    /><result property="createTime"    column="create_time"    /><result property="updateTime"    column="update_time"    /><result property="createBy"    column="create_by"    /><result property="updateBy"    column="update_by"    /><result property="remark"    column="remark"    /><result property="vmCount"    column="vm_count"    /><!-- 将column(数据库字段)作为条件传到select中进行条件查询,结果封装到property中,因因property为类对象,所以指定了JavaType(类) --><association property="region" javaType="Region" column="region_id" select="com.dkd.manage.mapper.RegionMapper.selectRegionById"/><association property="partner" javaType="Partner" column="partner_id" select="com.dkd.manage.mapper.PartnerMapper.selectPartnerById"/>
</resultMap><!-- id与函数名相同,resultMap为最终返回类型:NodeVo -->
<select id="selectNodeVoList" resultMap="NodeVoResult"><!-- 分组查询每个点位下的设备数量 -->SELECTn.id,n.node_name,n.address,n.business_type,n.region_id,n.partner_id,n.create_time,n.update_time,n.create_by,n.update_by,n.remark,COUNT(v.id) AS vm_countFROMtb_node nLEFT JOINtb_vending_machine v ON n.id = v.node_id<where><if test="nodeName != null  and nodeName != ''"> and n.node_name like concat('%', #{nodeName}, '%')</if><if test="regionId != null "> and n.region_id = #{regionId}</if><if test="partnerId != null "> and n.partner_id = #{partnerId}</if></where>GROUP BYn.id
</select>

3.修改service层

INodeService

java">/*** 查询点位管理列表* @param node* @return NodeVo集合*/
public List<NodeVo> selectNodeVoList(Node node);

NodeServiceImpl

java">/*** 查询点位管理列表** @param node* @return NodeVo集合*/
@Override
public List<NodeVo> selectNodeVoList(Node node) {return nodeMapper.selectNodeVoList(node);
}

4. 修改controller层

NodeController

java">/*** 查询点位管理列表*/
@PreAuthorize("@ss.hasPermi('manage:node:list')")
@GetMapping("/list")
public TableDataInfo list(Node node)
{startPage(); //开始分页List<NodeVo> voList = nodeService.selectNodeVoList(node); //以node为条件进行查询,结果分装到NOdeVo类中return getDataTable(voList); //将NodeVo转为TableDataInfo
}

5.前端修改

node/index.vue

<!-- 点位列表 -->
<el-table v-loading="loading" :data="nodeList" @selection-change="handleSelectionChange"><el-table-column type="selection" width="55" align="center" /><el-table-column label="序号" type="index" width="50" align="center" prop="id" /><el-table-column label="点位名称" align="center" prop="nodeName" /><el-table-column label="所在区域" align="center" prop="region.regionName" /><el-table-column label="商圈类型" align="center" prop="businessType"><template #default="scope"><dict-tag :options="business_type" :value="scope.row.businessType" /></template></el-table-column><el-table-column label="合作商" align="center" prop="partner.partnerName" /><el-table-column label="详细地址" align="center" prop="address" show-overflow-tooltip="true"/><el-table-column label="操作" align="center" class-name="small-padding fixed-width"><template #default="scope"><el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['manage:node:edit']">修改</el-button><el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['manage:node:remove']">删除</el-button></template></el-table-column></el-table>

6.补充区域查看详情

在region/index.vue视图组件中修改

<el-button link type="primary" @click="getRegionInfo(scope.row)" v-hasPermi="['manage:node:list']">查看详情</el-button><!-- 查看详情对话框 -->
<el-dialog title="区域详情" v-model="regionInfoOpen" width="500px" append-to-body><el-form-item label="区域名称" prop="regionName"><el-input v-model="form.regionName" disabled /></el-form-item><label>包含点位:</label><el-table :data="nodeList"><el-table-column label="序号" type="index" width="50" align="center" /><el-table-column label="点位名称" align="center" prop="nodeName" /><el-table-column label="设备数量" align="center" prop="vmCount" /></el-table></el-dialog><script>javascript">import { listNode } from "@/api/manage/node";import { loadAllParams } from "@/api/page";/* 查看详情按钮操作 */const nodeList = ref([]);const regionInfoOpen = ref(false);function getRegionInfo(row) {// 查询区域信息reset();const _id = row.idgetRegion(_id).then(response => {form.value = response.data;});// 查询点位列表loadAllParams.regionId = row.id;listNode(loadAllParams).then(response => {nodeList.value = response.rows;});regionInfoOpen.value = true;
</script>

7.数据完整性

现在我们要思考一个问题,当我们删除区域或合作商数据时,与之关联的点位数据该如何处理?
在这里插入图片描述

在默认情况下,由于我们在创建点位表时通过AI设置了外键约束,并配置了级联删除操作,所以删除区域或合作商会导致其关联的点位数据一并被删除。从技术角度来看,这是符合数据库的外键约束规则的。
但是,从业务角度来看,这种做法可能不太合适。想象一下,如果一个区域下有多个点位,一次误操作就可能导致所有的点位数据及其关联的设备信息被一并删除,这显然是我们不愿意看到的。
因此,我们需要对级联操作进行修改,将其改为限制删除。这样,当尝试删除一个区域或合作商时,如果它下面还有关联的点位数据,数据库将不会允许删除操作,并会给出错误提示。

使用Navicat修改tb_node表:
在这里插入图片描述

CASCADE(级联操作):当父表中的某行记录被删除或更新时,与其关联的所有子表中的匹配行也会自动被删除或更新。这种方式适用于希望保持数据一致性的场景,即父记录不存在时,相关的子记录也应该被移除。
SET NULL(设为空):若父表中的记录被删除或更新,子表中对应的外键字段会被设置为NULL。选择此选项的前提是子表的外键列允许为NULL值。这适用于那些子记录不再需要明确关联到任何父记录的情况。
RESTRICT(限制):在尝试删除或更新父表中的记录之前,数据库首先检查是否有相关联的子记录存在。如果有,则拒绝执行删除或更新操作,以防止意外丢失数据或破坏数据关系的完整性。这是一种保守策略,确保数据间的引用完整性。
NO ACTION(无操作):在标准SQL中,NO ACTION是一个关键字,它要求数据库在父表记录被删除或更新前,检查是否会影响子表中的相关记录。在MySQL中,NO ACTION的行为与RESTRICT相同,即如果子表中有匹配的行,则禁止执行父表的删除或更新操作。这意味着如果存在依赖关系,操作将被阻止,从而保护数据的参照完整性。
修改完毕后,如果你尝试进行删除操作,会发现数据库的完整性约束生效了,它会阻止删除操作并给出错误提示。但是,这个错误提示信息可能对于用户来说不够友好,可能会让用户感到困惑。
在这里插入图片描述
SQLIntegrityConstraintViolationException是Java中的一个异常类,这个类通常用于表示SQL数据库操作中的完整性约束违反异常
例如:外键约束、唯一约束等。当数据库操作违反了这些约束时,就会抛出这个异常。
这个错误是由于外键约束导致的。它表明在删除或更新父表的行时,存在外键约束,子表中的相关行会受到影响。
是因为在删除tb_region表中的行时,tb_node表中的region_id外键约束会阻止操作。
如果你在使用Spring框架进行数据库操作,可能会先遇到DataIntegrityViolationException,它是对SQLIntegrityConstraintViolationException的一个更高层次的抽象,旨在提供一种更加面向应用的错误表示。
而SQLIntegrityConstraintViolationException是更底层的异常,直接来源于数据库驱动,包含更多底层数据库相关的细节。
在实际开发中,推荐捕获并处理DataIntegrityViolationException,因为它更符合Spring应用的异常处理模式,同时也可以通过其内部的cause(原因)属性来获取具体的SQLIntegrityConstraintViolationException,进而获取详细的错误信息。

为了提升用户体验,我们可以使用Spring Boot框架的全局异常处理器来捕获这些错误信息,并返回更友好的提示信息给用户。这样,当用户遇到这种情况时,他们将收到一个清晰、易懂的提示,告知他们操作无法完成的原因。
修改全局异常处理器,添加以下内容
在这里插入图片描述

java">/*** 数据完整性异常*/
@ExceptionHandler(DataIntegrityViolationException.class)
public AjaxResult handelDataIntegrityViolationException(DataIntegrityViolationException e) {if (e.getMessage().contains("foreign")) {return AjaxResult.error("无法删除,有其他数据引用");}return AjaxResult.error("您的操作违反了数据库中的完整性约束");
}

http://www.ppmy.cn/news/1536855.html

相关文章

项目管理-信息技术发展

1、计算机软硬件 2、计算机网络 1&#xff09;定义 2&#xff09;分类&#xff1a;PAN LAN MAN WAN 公用网 专用网 3&#xff09;网络协议 语法 语义 时许 4&#xff09;网络标准协议 7层 5&#xff09;IEEE 802 规范 6&#xff09;TCP/IP 协议 7) SDN 软件定义网…

C++面试速通宝典——13

208. class里面定义int a&#xff0c;如果不实现构造函数&#xff0c;实例化这个类&#xff0c;a的值是&#xff1f; ‌‌‌‌  答&#xff1a;a的值是未定义的&#xff08;在C标准中成为“未初始化”&#xff09;。 解释&#xff1a; ‌‌‌‌  在C中&#xff0c;如果一…

Leetcode: 0001-0010题速览

Leetcode: 0001-0010题速览 本文材料来自于LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer&#xff08;第 2 版&#xff09;》、《程序员面试金典&#xff08;第 6 版&#xff09;》题解 遵从开源协议为知识共享 版权归属-相同方式…

大厂面试真题-说说AtomicInteger 线程安全原理

基础原子类&#xff08;以 AtomicInteger 为例&#xff09;主要通过 CAS 自旋 volatile 相结合的方案实现&#xff0c;既保障了 变量操作的线程安全性&#xff0c;又避免了 synchronized 重量级锁的高开销&#xff0c;使得 Java 程序的执行效率大为 提升。 CAS 用于保障变量…

JavaScript中的异步编程:从回调到Promise

在JavaScript中&#xff0c;异步编程是一项至关重要的技能&#xff0c;它允许我们在不阻塞主线程的情况下执行耗时操作&#xff0c;如网络请求、文件读取或定时任务。随着JavaScript的发展&#xff0c;异步编程的模式也在不断演进&#xff0c;从最初的回调函数&#xff0c;到现…

基于深度学习的持续的知识积累与转移

基于深度学习的持续知识积累与转移是指利用深度学习技术在多个任务或领域中有效地获取、更新和应用知识。这一过程能够提高模型在新任务上的性能&#xff0c;同时减少对大量标注数据的依赖。以下是这一领域的主要内容&#xff1a; 1. 持续知识积累 在线学习&#xff1a;模型能…

ARP(Address Resolution Protocol,地址解析协议)

ARP(Address Resolution Protocol,地址解析协议)是一个网络协议,主要用于在局域网(LAN)中通过IP地址查找对应的MAC地址。它是位于网络层和链路层之间的重要协议,帮助设备通过已知的IP地址找到网络中对应的物理硬件地址(即MAC地址),以便数据能够正确地传输到目标设备。…

AI开发者工具的双子星:Cursor与ChatGPT Canvas的区别

01—Cursor&#xff1a;沉浸式的开发体验 Cursor是一款旨在为开发者提供无缝编程体验的工具。它将AI的功能深度嵌入到开发者熟悉的环境中&#xff0c;便于在编码过程中获得即时帮助。开发者无需离开自己的操作界面&#xff0c;AI就能自动为其提供代码补全、错误检查和优化建议…