当前位置: 首页 > news >正文

第四阶段10-添加类别,类别列表mapper层,service层,controller层

63. 添加类别–Mapper层

插入类别数据的功能此前已经完成!

64. 添加类别–Service层

在项目的根包下创建pojo.dto.CategoryAddNewDTO类:

@Data
public class CategoryAddNewDTO implements Serializable {/*** 类别名称*/private String name;/*** 父级类别id,如果无父级,则为0*/private Long parentId;/*** 关键词列表,各关键词使用英文的逗号分隔*/private String keywords;/*** 排序序号*/private Integer sort;/*** 图标图片的URL*/private String icon;/*** 是否启用,1=启用,0=未启用*/private Integer enable;/*** 是否显示在导航栏中,1=启用,0=未启用*/private Integer isDisplay;}

在项目的根包下创建service.ICategoryService接口,并在接口中添加抽象方法:

public interface ICategoryService {void addNew(CategoryAddNewDTO categoryAddNewDTO);
}

在项目的根包下创建service.impl.CategoryServiceImpl类,实现以上接口,并在类上添加@Service注解,然后,实现接口中的方法:

@Service
public class CategoryServiceImpl implements ICategoryService {public void addNew(CategoryAddNewDTO categoryAddNewDTO) {// 调用Mapper对象的countByName()检查类别名称是否已经被占用// 是:抛出异常(ERR_CONFLICT)// 如果parentId不是0,调用Mapper对象的getStandardById()查询类别详情// 判断查询结果是否为null// 是:父级类别不存在,抛出异常(NOT_FOUND)// depth(深度)的值:如果父级类别id为0,则depth为1,否则,depth为父级depth+1// 创建Category类的对象// 将参数对象中的各属性值复制到以上新创建的Category类的对象中// 补全Category类的对象的属性值:depth// 补全Category类的对象的属性值:isParent >>> 固定为0// 调用Mapper对象的insert()方法插入类别数据// 如果现在添加的类别的父级类别不是0,// 如果父级类别的isParent仍为0// 则将父级类别的isParent更新为1}}

具体实现为:

@Override
public void addNew(CategoryAddNewDTO categoryAddNewDTO) {log.debug("开始处理【添加类别】的业务,参数:{}", categoryAddNewDTO);// 调用Mapper对象的countByName()检查类别名称是否已经被占用String name = categoryAddNewDTO.getName();int countByName = categoryMapper.countByName(name);if (countByName > 0) {// 是:抛出异常(ERR_CONFLICT)String message = "添加类别失败,尝试添加的类别名称【" + name + "】已经被占用!";log.warn(message);throw new ServiceException(ServiceCode.ERR_CONFLICT, message);}Integer depth = 1;CategoryStandardVO parentCategory = null;Long parentId = categoryAddNewDTO.getParentId();if (parentId != 0) {// 如果parentId不是0,调用Mapper对象的getStandardById()查询类别详情parentCategory = categoryMapper.getStandardById(parentId);// 判断查询结果是否为nullif (parentCategory == null) {// 是:父级类别不存在,抛出异常(NOT_FOUND)String message = "添加类别失败,选定的父级类别不存在!";log.warn(message);throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);} else {depth = parentCategory.getDepth() + 1;}}// 创建Category类的对象Category category = new Category();// 将参数对象中的各属性值复制到以上新创建的Category类的对象中BeanUtils.copyProperties(categoryAddNewDTO, category);// 补全Category类的对象的属性值:depthcategory.setDepth(depth);// 补全Category类的对象的属性值:isParent >>> 固定为0category.setIsParent(0);// 调用Mapper对象的insert()方法插入类别数据categoryMapper.insert(category);// 如果现在添加的类别的父级类别不是0if (parentId != 0) {// 如果父级类别的isParent仍为0if (parentCategory.getIsParent() == 0) {// 则将父级类别的isParent更新为1Category updateParentCategory = new Category();updateParentCategory.setId(parentId);updateParentCategory.setIsParent(1);categoryMapper.update(updateParentCategory);}}
}

在项目的src/test/java下的根包下创建CategoryServiceTests类,对以上方法进行测试:

@Slf4j
@SpringBootTest
public class CategoryServiceTests {@AutowiredICategoryService service;@Testvoid addNew() {CategoryAddNewDTO categoryAddNewDTO = new CategoryAddNewDTO();categoryAddNewDTO.setParentId(74L);categoryAddNewDTO.setName("热带水果");try {service.addNew(categoryAddNewDTO);log.debug("添加类别成功!");} catch (ServiceException e) {log.debug("捕获到异常,其中的消息:{}", e.getMessage());}}}

65. 添加类别–Controller层

在项目的根包下创建controller.CategoryController类,在类上添加@RestController注解和@RequestMapping("/categories")注解,在类中自动装配ICategoryService类型的对象:

@RestController
@RequestMapping("/categories")
public class CategoryController {@Autowiredprivate ICategoryService categoryService;
}

然后,在此类中处理请求:

@PostMapping("/add-new")
public JsonResult<Void> addNew(CategoryAddNewDTO categoryAddNewDTO) {log.debug("xxx");categoryService.addNew(categoryAddNewDTO);return JsonResult.ok();
}

完成后,重启项目,可以通过在线API文档进行调试。

调试通过后,应该补充在线API文档的相关说明。

提示:接下来,在课上不再对请求参数的基本格式进行检查。

66. 删除类别–Mapper层

67. 删除类别–Service层

ICategoryService接口中添加抽象方法:

/*** 根据id删除类别** @param id 类别id*/
void delete(Long id);

CategoryServiceImpl中实现以上方法:

public void delete(Long id) {// 调用Mapper对象的getStandardById()执行查询// 判断查询结果是否为null// 是:数据已经不存在,抛出异常(NOT_FOUND)// 判断以上查询结果中的isParent是否为1// 是:当前尝试删除的是父级类别,抛出异常(CONFLICT)// 调用BrandCategoryMapper对象的countByCategory()执行统计// 判断统计结果是否大于0// 是:当前尝试删除的类别关联到了某些品牌,抛出异常(CONFLICT)// 调用CategoryAttributeTemplateMapper对象的countByCategory()执行统计// 判断统计结果是否大于0// 是:当前尝试删除的类别关联到了某些属性模板,抛出异常(CONFLICT)// 调用SpuMapper对象的countByCategory()执行统计// 判断统计结果是否大于0// 是:当前尝试删除的类别关联到了某些SPU,抛出异常(CONFLICT)// 调用Mapper对象的deleteById()执行删除// 从此前的查询结果中找到当前删除的类别的父级类别ID// 判断父级类别ID是否不为0// 调用Mapper对象的countByParentId()执行统计// 判断统计结果是否等于0// 是:将父级类别的isParent更新为0
}

具体实现为:

@Override
public void delete(Long id) {// 调用Mapper对象的getStandardById()执行查询CategoryStandardVO currentCategory = categoryMapper.getStandardById(id);// 判断查询结果是否为nullif (currentCategory == null) {// 是:数据已经不存在,抛出异常(NOT_FOUND)String message = "删除类别失败,尝试删除的类别不存在!";log.warn(message);throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);}// 判断以上查询结果中的isParent是否为1if (currentCategory.getIsParent() == 1) {// 是:当前尝试删除的是父级类别,抛出异常(CONFLICT)String message = "删除类别失败,尝试删除的类别仍包含子级类别!";log.warn(message);throw new ServiceException(ServiceCode.ERR_CONFLICT, message);}{// 调用BrandCategoryMapper对象的countByCategory()执行统计int count = brandCategoryMapper.countByCategory(id);// 判断统计结果是否大于0if (count > 0) {// 是:当前尝试删除的类别关联到了某些品牌,抛出异常(CONFLICT)String message = "删除类别失败,尝试删除的类别关联了某些品牌!";log.warn(message);throw new ServiceException(ServiceCode.ERR_CONFLICT, message);}}{// 调用CategoryAttributeTemplateMapper对象的countByCategory()执行统计int count = categoryAttributeTemplateMapper.countByCategory(id);// 判断统计结果是否大于0if (count > 0) {// 是:当前尝试删除的类别关联到了某些属性模板,抛出异常(CONFLICT)String message = "删除类别失败,尝试删除的类别关联了某些属性模板!";log.warn(message);throw new ServiceException(ServiceCode.ERR_CONFLICT, message);}}{// 调用SpuMapper对象的countByCategory()执行统计int count = spuMapper.countByCategory(id);// 判断统计结果是否大于0if (count > 0) {// 是:当前尝试删除的类别关联到了某些SPU,抛出异常(CONFLICT)String message = "删除类别失败,尝试删除的类别关联了某些SPU!";log.warn(message);throw new ServiceException(ServiceCode.ERR_CONFLICT, message);}}// 调用Mapper对象的deleteById()执行删除log.debug("即将执行删除类别,参数:{}", id);categoryMapper.deleteById(id);// 从此前的查询结果中找到当前删除的类别的父级类别IDLong parentId = currentCategory.getParentId();// 判断父级类别ID是否不为0if (parentId != 0) {// 调用Mapper对象的countByParentId()执行统计int count = categoryMapper.countByParentId(parentId);// 判断统计结果是否等于0if (count == 0) {// 是:将父级类别的isParent更新为0Category parentCategory = new Category();parentCategory.setId(parentId);parentCategory.setIsParent(0);categoryMapper.update(parentCategory);}}
}

CategoryServiceTests中编写并执行测试:

@Test
void delete() {Long id = 74L;try {service.delete(id);log.debug("删除类别成功!");} catch (ServiceException e) {log.debug("捕获到异常,其中的消息:{}", e.getMessage());}
}

相关文章:

第四阶段10-添加类别,类别列表mapper层,service层,controller层

63. 添加类别–Mapper层 插入类别数据的功能此前已经完成&#xff01; 64. 添加类别–Service层 在项目的根包下创建pojo.dto.CategoryAddNewDTO类&#xff1a; Data public class CategoryAddNewDTO implements Serializable {/*** 类别名称*/private String name;/*** 父…...

linux内核启动分析(一)

文章目录1.HEAD1.preserve_boot_args1.1 __inval_dcache_area2.el2_setup3. set_cpu_boot_mode_flag4. __create_page_tables4.1map_memory5. __cpu_setup6. __primary_switch6.1 __enable_mmu6.2 __primary_switched最近工作中经常使用飞腾E2000的开发版&#xff0c;也遇到一些…...

wireshark常见使用操作讲解以及几个故障解决案例分享

&#xff08;1&#xff09;网卡选择 对于电脑本身有多个网卡的时候&#xff0c;选择网卡就成为了一个困惑的地方&#xff0c;其实这里很简单&#xff0c;只要把鼠标放在对应的网卡上面就可以看到地址等信息&#xff0c;就容易判断出来了。 &#xff08;2&#xff09;过滤器 直…...

利用逻辑分析仪解析串口通讯数据

利用逻辑分析仪解析串口通讯数据&#x1f527;采用的是市面上最为广泛使用的USB逻辑分析仪: &#x1f4da;资料下载&#xff1a; 链接: https://pan.baidu.com/s/1c9lwWDbtJxaJED-kzSbiJg 提取码: 5vnr&#x1f528;测试工具为&#xff1a;Logic 2.4.6&#xff0c;也可以使用Pu…...

新整理的前端面试题

pinia和vuex的区别&#xff08;1&#xff09;pinia它没有mutation,他只有state&#xff0c;getters&#xff0c;action【同步、异步】使用他来修改state数据&#xff08;2&#xff09;pinia他默认也是存入内存中&#xff0c;如果需要使用本地存储&#xff0c;在配置上比vuex麻烦…...

数据仓库-数仓分层

层级 全拼 职责划分 ODS(源数据层) Operational DataStore ODS层存储最原始的数据&#xff0c; 对数据不做任何加工处理&#xff1b; 源数据主要来自业务数据库和日志&#xff0c;这些数据是用户操作业务系统产生&#xff0c;所以叫操作型数据(Operational Data) 。 DWD(…...

【Linux】Linux根文件系统扩容

场景&#xff1a;根文件系统需要至少100GB的剩余空间&#xff0c;但是目前就剩余91GB。因此&#xff0c;我们需要对根文件系统进行扩容。# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 3.9G 0 3.9G 0% /dev tmpfs …...

RPC编程:Hessian RPC一个老的RPC框架(一)

RPC编程&#xff1a;Hessian RPC一个老的RPC框架一&#xff1a;Hessian RPC1&#xff1a;Hession RPC一个老的RPC框架2&#xff1a;老&#xff0c;为什么还要研究&#xff1f;3&#xff1a;Hession RPC概念二&#xff1a;Hessian RPC设计思想1&#xff1a;Hession依赖于服务器2…...

逆向 x蜂窝 zzzghostsigh

逆向 x蜂窝 zzzghostsigh 版本 9.3.7 新版本是64位的so charles 抓包 目标字段 zzzghostsigh frida java function hook_xPreAuthencode() {Java.perform(function() {var helper Java.use("com.mfw.tnative.AuthorizeHelper");helper.xPreAuthencode.implemen…...

QML 鼠标事件

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 QML 中有一些元素本身是不具备交互能力的(例如:Rectangle、Text、Image 等),那么如何通过鼠标来控制它们的行为呢?这里就需要用到 MouseArea 元素了,它继承于 Item 且不可见,通常需要与可见元素结合使…...

极智项目 | 实战pytorch arcface人脸识别

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多经验分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍 实战pytorch arcface人脸识别&#xff0c;并提供完整项目源码。 本文介绍的实战arcface人脸识别项目&#xff0c;提供完整的可以一键训练、测试的项目工程…...

【IP技术】ipv4和ipv6是什么?

IPv4和IPv6是两种互联网协议&#xff0c;用于在互联网上标识和寻址设备。IPv4&#xff08;Internet Protocol version 4&#xff09;是互联网协议的第四个版本&#xff0c;是当前广泛使用的互联网协议。IPv4地址由32位二进制数构成&#xff0c;通常表示为4个十进制数&#xff0…...

linux基本功系列之uniq命令实战

文章目录前言一. uniq的命令介绍二. 语法格式及常用选项三. 参考案例3.1 统计行数3.2 对文本进行去重3.3 显示不重复的行3.4 仅显示重复的行&#xff0c;且显示重复的行的所有行3.5 忽略字母大小写总结前言 大家好&#xff0c;又见面了&#xff0c;我是沐风晓月&#xff0c;本…...

六、SpringBoot项目搭建

日志 Java 主流日志工具库 统一接口 什么是 REST&#xff1f; Representational State Transfer——“表现层状态转化”。可以总结为一句话&#xff1a;REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征&#xff0c;对于同一个资源的一组不…...

【LeetCode】2363. 合并相似的物品

2363. 合并相似的物品 题目描述 给你两个二维整数数组 items1 和 items2 &#xff0c;表示两个物品集合。每个数组 items 有以下特质&#xff1a; items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 &#xff0c;weighti 表示第 i 件物品的 重量 。items 中每…...

华为OD机试题,用 Java 解【出租车计费】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果

论文题目&#xff1a;《Improving Face Recognition from Hard Samples via Distribution Distillation Loss》 论文地址&#xff1a;https://arxiv.org/pdf/2002.03662v3.pdf 代码地址&#xff1a;https://github.com/HuangYG123/DDL 1.前言及相关工作 Large facial variatio…...

如何管理好仓库/库房?

仓库管理是企业管理中不可缺少的一部分&#xff0c;事关企业能否正常运行的关键之一&#xff0c;古人有云&#xff1a;“三军未动粮草先行”&#xff0c;一个企业仓库管理做不好&#xff0c;他的生产管理肯定也是做不好的&#xff0c;不是说生产管理人员的管理能力不具备&#…...

Unity Lighting -- Unity的光源简介

在主菜单栏中&#xff0c;点击Window -> Rendering -> Light Explorer打开光源管理器&#xff0c;这个标签页可以看到场景中所有的光源&#xff0c;包括每个光源的类型&#xff0c;形状&#xff0c;模式&#xff0c;颜色&#xff0c;强度&#xff0c;阴影等信息。 在主菜…...

Android仿网易云音乐歌单详情页

效果图实现思路&#xff1a;1、Activity设置自定义Shared Element切换动画2、透明状态栏&#xff08;透明Toolbar,使背景图上移&#xff09;3、Toolbar底部增加和背景一样的高斯模糊图&#xff0c;并上移图片&#xff08;为了使背景图的底部作为Toolbar的背景&#xff09;4、上…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

SpringTask-03.入门案例

一.入门案例 启动类&#xff1a; package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...