菜品管理(day03)

ops/2025/1/18 8:07:02/

公共字段自动填充

问题分析

业务表中的公共字段:

而针对于这些字段,我们的赋值方式为:

在新增数据时, 将createTime、updateTime 设置为当前时间, createUser、updateUser设置为当前登录用户ID。
在更新数据时, 将updateTime 设置为当前时间, updateUser设置为当前登录用户ID。

问题:代码冗余、不便于后期维护

实现思路

有四个公共字段,需要在新增/更新中进行赋值操作, 具体情况如下:

实现步骤:

  1. 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法
  2. 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值
  3. 在 Mapper 的方法上加入 AutoFill 注解

技术点:枚举、注解、AOP、反射

java--反射(reflection)_反射 reflection java-CSDN博客

SpringBootWeb 事务&AOP(day13)-CSDN博客

java -- 枚举和注解_java 枚举-CSDN博客

代码开发

自定义注解 AutoFill

java">package com.sky.annotation;import com.sky.enumeration.OperationType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义注解,用于标识某个方法需要进行功能字段自行填充
* @author 石头
* @version 1.0
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {//数据库操作类型:UPDATE INSERTOperationType value();
}

Java中自定义注解的使用详解_java自定义注解使用-CSDN博客

自定义切面 AutoFillAspect

java">package com.sky.aspect;import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.LocalDateTime;/*** 自定义切面类,实现公告字段自动填充处理逻辑*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 切入点*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut() {}/*** 通知 自动填充公共字段* @param joinPoint*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("公共字段自动填充...");//获取到当前被拦截方法上的数据库操作类型MethodSignature signature = (MethodSignature)joinPoint.getSignature();//获得方法签名对象//获得方法上的注解AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);//获得注解中的操作类型OperationType operationType = autoFill.value();//获取到当前被拦截的方法的参数---实体对象Object[] args = joinPoint.getArgs();//获取当前目标方法的参数if (args == null || args.length == 0) { //防止空指针return;}//实体对象Object entity = args[0];//准备赋值的数据LocalDateTime time = LocalDateTime.now();Long empId = BaseContext.getCurrentId();//根据当前不同的操作类型,为对应的属性通过反射赋值if (operationType == OperationType.INSERT) {//当前执行的是insert操作,为4个字段赋值try {//获得set方法对象----MethodMethod setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通过反射调用目标对象的方法setCreateTime.invoke(entity, time);setUpdateTime.invoke(entity, time);setCreateUser.invoke(entity, empId);setUpdateUser.invoke(entity, empId);} catch (Exception ex) {log.error("公共字段自动填充失败:{}", ex.getMessage());}}else {//当前执行的是update操作,为2个字段赋值try {//获得set方法对象----MethodMethod setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//通过反射调用目标对象的方法setUpdateTime.invoke(entity, time);setUpdateUser.invoke(entity, empId);} catch (Exception ex) {log.error("公共字段自动填充失败:{}", ex.getMessage());}}}}

Mapper接口的方法上加入 AutoFill 注解

java">/*** 插入数据* @param category*/
@AutoFill(OperationType.INSERT)
@Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, update_user)" +" VALUES" +" (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
void insert(Category category);/*** 根据id修改分类* @param category*/
@AutoFill(OperationType.UPDATE)
void update(Category category);

将业务层为公共字段赋值的代码注释掉

功能测试

通过观察控制台输出的SQL来确定公共字段填充是否完成

新增菜品

需求分析和设计

产品原型

业务规则:

  • 菜品名称必须是唯一的
  • 菜品必须属于某个分类下,不能单独存在
  • 新增菜品时可以根据情况选择菜品的口味
  • 每个菜品必须对应一张图片

接口设计:

根据类型查询分类(已完成)
文件上传
新增菜品

根据类型查询分类

文件上传

新增菜品


数据库设计(dish菜品表和dish_flavor口味表):

代码开发

开发文件上传接口:

开发文件上传接口:



开发新增菜品接口:

java">@Data
public class DishDTO implements Serializable {private Long id;//菜品名称private String name;//菜品分类idprivate Long categoryId;//菜品价格private BigDecimal price;//图片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//口味private List<DishFlavor> flavors = new ArrayList<>();}

开发新增菜品接口:




java"><!--useGeneratedKeys:true 表示获取主键值keyProperty="id" 表示将主键值赋给id属性
-->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into dish (status, name, category_id, price, image, description, create_time, update_time, create_user,update_user)values (#{status}, #{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime},#{createUser}, #{updateUser})
</insert>


java"><insert id="insertBatch">insert into dish_flavor(dish_id, name, value) values<foreach collection="flavors" item="dishFlavor" separator=",">(#{dishFlavor.dishId},#{dishFlavor.name},#{dishFlavor.value})</foreach>
</insert>

功能测试

可以通过接口文档进行测试,也可以进行前后端联调测试

菜品分页查询

需求分析和设计

产品原型:

业务规则:

  • 根据页码展示菜品信息
  • 每页展示10条数据
  • 分页查询时可以根据需要输入菜品名称、菜品分类、菜品状态进行查询

接口设计:

代码开发

根据菜品分页查询接口定义设计对应的DTO

java">@Data
public class DishPageQueryDTO implements Serializable {private int page;private int pageSize;//菜品名称private String name;//分类idprivate Integer categoryId;//状态 0表示禁用 1表示启用private Integer status;}

根据菜品分页查询接口定义设计对应的VO

java">public class DishVO implements Serializable {private Long id;//菜品名称private String name;//菜品分类idprivate Long categoryId;//菜品价格private BigDecimal price;//图片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//更新时间private LocalDateTime updateTime;//分类名称private String categoryName;//菜品关联的口味private List<DishFlavor> flavors = new ArrayList<>();}

根据接口定义创建DishControllerpage分页查询方法:

如果前端是通过 URL 的查询字符串(query string)或路径变量(path variables)来传递数据的(比如 GET 请求中的参数),那么在后端就不需要使用 @RequestBody

DishService 中扩展分页查询方法:

DishServiceImpl 中实现分页查询方法:

DishMapper 接口中声明 pageQuery 方法:

DishMapper.xml 中编写SQL

功能测试

可以通过接口文档进行测试,最后完成前后端联调测试即可

删除菜品

需求分析和设计

产品原型:

业务规则:

  • 可以一次删除一个菜品,也可以批量删除菜品
  • 起售中的菜品不能删除
  • 被套餐关联的菜品不能删除
  • 删除菜品后,关联的口味数据也需要删除掉

接口设计:

数据库设计:

代码开发




创建SetmealDishMapper,声明getSetmealIdsByDishIds方法,并在xml文件中编写SQL

DishMapper.xml中声明deleteById方法并配置SQL

DishFlavorMapper中声明deleteByDishId方法并配置SQL

 

功能测试

通过Swagger接口文档进行测试,通过后再前后端联调测试即可

修改菜品

需求分析和设计

产品原型:

接口设计:

根据 id 查询菜品
根据类型查询分类(已实现)
文件上传(已实现)
修改菜品

根据id查询菜品

修改菜品


代码开发

根据id查询菜品 接口开发:

根据id查询菜品 接口开发:

修改菜品 接口开发:

功能测试

通过Swagger接口文档进行测试,通过后再前后端联调测试即可

上一节:

员工管理、分类管理(day02)-CSDN博客

下一节:


http://www.ppmy.cn/ops/151041.html

相关文章

【telegraf安装】centos主机安装和docker安装

目标 在服务器以centos和docker安装telegraf。 一、centos主机安装 In your terminal, enter the following command to add the InfluxData repository to the yum configuration: cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo [influxdb] name InfluxDat…

Kotlin语言的数据库交互

Kotlin语言的数据库交互 引言 随着移动设备和互联网技术的迅猛发展&#xff0c;应用程序已经成为现代生活中不可或缺的一部分。在这些应用程序中&#xff0c;数据库扮演着至关重要的角色&#xff0c;存储着用户的数据及应用的状态。Kotlin作为一种现代化的编程语言&#xff0…

《Keras 3 在 TPU 上的肺炎分类》

Keras 3 在 TPU 上的肺炎分类 作者&#xff1a;Amy MiHyun Jang创建日期&#xff1a;2020/07/28最后修改时间&#xff1a;2024/02/12描述&#xff1a;TPU 上的医学图像分类。 &#xff08;i&#xff09; 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 简介 设置 本教程将介…

58,【8】BUUCTF [PwnThyBytes 2019]Baby_SQL1

进入靶场 和2次注入的页面很像 不过养成查看源代码的好习惯 先访问source.zip 下载后解压&#xff0c;发现两个文件 第一个文件夹打开又有4个PHP文件 那还是先看index.php文件好了 有PHP和HTML两部分&#xff0c;下面是PHP部分代码&#xff08;HTML太长了&#xff0c;先放一…

github 端口22 超时问题解决

github 端口22 超时问题解决 问题描述报错信息解决方案步骤1步骤2步骤3 问题描述 搬了个公司后发现自己的sourcetree 以及 本地命令行在拉取代码或者clone时均报错&#xff0c;根据网友的解决方案&#xff0c;做了个整理 报错信息 $ git pull project develop ssh: connect …

无人设备遥控器之操控手法篇

无人设备遥控器的操控手法主要依赖于具体的设备类型&#xff08;如无人机、遥控机器人等&#xff09;以及用户所选用的操控模式。 一、无人机遥控器操控手法 无人机遥控器通常配备有左右两个摇杆和多个功能按键。左右摇杆的功能可能因“手”&#xff08;遥控模型&#xff09;的…

SparkSQL数据源与数据存储

文章目录 1. 大数据分析流程2. Spark SQL数据源2.1 SparkSQL常见数据源2.2 SparkSQL支持的文本格式2.3 加载外部数据源步骤 3. 本地文件系统加载数据3.1 本地文件系统加载JSON格式数据3.1.1 概述3.1.2 案例演示 3.2 本地文件系统加载CSV格式数据3.2.1 概述3.2.2 案例演示 3.3 本…

每打开一个chrome页面都会【自动打开F12开发者模式】,原因是 使用HBuilderX会影响谷歌浏览器的浏览模式

打开 HBuilderX&#xff0c;点击 运行 -> 运行到浏览器 -> 设置web服务器 -> 添加chrome浏览器安装路径 chrome谷歌浏览器插件 B站视频下载助手插件&#xff1a; 参考地址&#xff1a;Chrome插件 - B站下载助手&#xff08;轻松下载bilibili哔哩哔哩视频&#xff09…