第四阶段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层 插入类别数据的功能此前已经完成! 64. 添加类别–Service层 在项目的根包下创建pojo.dto.CategoryAddNewDTO类: 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的开发版,也遇到一些…...
wireshark常见使用操作讲解以及几个故障解决案例分享
(1)网卡选择 对于电脑本身有多个网卡的时候,选择网卡就成为了一个困惑的地方,其实这里很简单,只要把鼠标放在对应的网卡上面就可以看到地址等信息,就容易判断出来了。 (2)过滤器 直…...
利用逻辑分析仪解析串口通讯数据
利用逻辑分析仪解析串口通讯数据🔧采用的是市面上最为广泛使用的USB逻辑分析仪: 📚资料下载: 链接: https://pan.baidu.com/s/1c9lwWDbtJxaJED-kzSbiJg 提取码: 5vnr🔨测试工具为:Logic 2.4.6,也可以使用Pu…...
新整理的前端面试题
pinia和vuex的区别(1)pinia它没有mutation,他只有state,getters,action【同步、异步】使用他来修改state数据(2)pinia他默认也是存入内存中,如果需要使用本地存储,在配置上比vuex麻烦…...
数据仓库-数仓分层
层级 全拼 职责划分 ODS(源数据层) Operational DataStore ODS层存储最原始的数据, 对数据不做任何加工处理; 源数据主要来自业务数据库和日志,这些数据是用户操作业务系统产生,所以叫操作型数据(Operational Data) 。 DWD(…...
【Linux】Linux根文件系统扩容
场景:根文件系统需要至少100GB的剩余空间,但是目前就剩余91GB。因此,我们需要对根文件系统进行扩容。# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 3.9G 0 3.9G 0% /dev tmpfs …...
RPC编程:Hessian RPC一个老的RPC框架(一)
RPC编程:Hessian RPC一个老的RPC框架一:Hessian RPC1:Hession RPC一个老的RPC框架2:老,为什么还要研究?3:Hession RPC概念二:Hessian RPC设计思想1: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人脸识别
欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文介绍 实战pytorch arcface人脸识别,并提供完整项目源码。 本文介绍的实战arcface人脸识别项目,提供完整的可以一键训练、测试的项目工程…...
【IP技术】ipv4和ipv6是什么?
IPv4和IPv6是两种互联网协议,用于在互联网上标识和寻址设备。IPv4(Internet Protocol version 4)是互联网协议的第四个版本,是当前广泛使用的互联网协议。IPv4地址由32位二进制数构成,通常表示为4个十进制数࿰…...
linux基本功系列之uniq命令实战
文章目录前言一. uniq的命令介绍二. 语法格式及常用选项三. 参考案例3.1 统计行数3.2 对文本进行去重3.3 显示不重复的行3.4 仅显示重复的行,且显示重复的行的所有行3.5 忽略字母大小写总结前言 大家好,又见面了,我是沐风晓月,本…...
六、SpringBoot项目搭建
日志 Java 主流日志工具库 统一接口 什么是 REST? Representational State Transfer——“表现层状态转化”。可以总结为一句话:REST 是所有 Web 应用都应该遵守的架构设计指导原则。面向资源是 REST 最明显的特征,对于同一个资源的一组不…...
【LeetCode】2363. 合并相似的物品
2363. 合并相似的物品 题目描述 给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质: items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 ,weighti 表示第 i 件物品的 重量 。items 中每…...
华为OD机试题,用 Java 解【出租车计费】问题
最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...
【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果
论文题目:《Improving Face Recognition from Hard Samples via Distribution Distillation Loss》 论文地址:https://arxiv.org/pdf/2002.03662v3.pdf 代码地址:https://github.com/HuangYG123/DDL 1.前言及相关工作 Large facial variatio…...
如何管理好仓库/库房?
仓库管理是企业管理中不可缺少的一部分,事关企业能否正常运行的关键之一,古人有云:“三军未动粮草先行”,一个企业仓库管理做不好,他的生产管理肯定也是做不好的,不是说生产管理人员的管理能力不具备&#…...
Unity Lighting -- Unity的光源简介
在主菜单栏中,点击Window -> Rendering -> Light Explorer打开光源管理器,这个标签页可以看到场景中所有的光源,包括每个光源的类型,形状,模式,颜色,强度,阴影等信息。 在主菜…...
Android仿网易云音乐歌单详情页
效果图实现思路:1、Activity设置自定义Shared Element切换动画2、透明状态栏(透明Toolbar,使背景图上移)3、Toolbar底部增加和背景一样的高斯模糊图,并上移图片(为了使背景图的底部作为Toolbar的背景)4、上…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...
