公共字段自动填充、菜品管理
一、公共字段填充
1.1、问题分析

1.2、实现思路

1.3、代码开发
1.3.1、自定义注解
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;@Target ( ElementType.METHOD )
@Retention ( RetentionPolicy.RUNTIME )
public @interface AutoFill {//通过枚举类型指定数据库操作的类型//UPDATE INSERTOperationType value();
}
1.3.2、切面类
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(){}/*** 前置通知,在通知中进行公共字段的赋值*/@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 now = LocalDateTime.now ();Long currentId = BaseContext.getCurrentId ();//根据当前不同的操作类型,为对应的属性通过反射赋值if (operationType==OperationType.INSERT ){//为四个公共字段赋值try {//通过反射获得方法Method setCreatTime = entity.getClass ().getDeclaredMethod ( AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class );Method setCreateUser = entity.getClass ().getDeclaredMethod (AutoFillConstant.SET_CREATE_USER , Long.class );Method setUpdateTime = entity.getClass ().getDeclaredMethod ( AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class );Method setUpdateUser = entity.getClass ().getDeclaredMethod ( AutoFillConstant.SET_UPDATE_USER, Long.class );//通过反射进行赋值setCreatTime.invoke ( entity,now );setCreateUser.invoke ( entity,currentId );setUpdateTime.invoke ( entity,now );setUpdateUser.invoke ( entity,currentId );} catch (Exception e) {e.printStackTrace ();}}else if (operationType==OperationType.UPDATE){try {Method setUpdateTime = entity.getClass ().getDeclaredMethod ( AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class );Method setUpdateUser = entity.getClass ().getDeclaredMethod ( AutoFillConstant.SET_UPDATE_USER, Long.class );setUpdateTime.invoke ( entity,now );setUpdateUser.invoke ( entity,currentId );} catch (Exception e) {e.printStackTrace ();}//为两个公共字段赋值}}}
二、新增菜品
2.1、需求分析和设计






2.2、文件上传
1.Controller层
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.UUID;/*** 通用接口*/
@RestController
@RequestMapping("/admin/common")
@Slf4j
@Api(tags = "通用接口")
public class CommonController {@Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* @param file* @return*/@PostMapping("/upload")
@ApiOperation ( "文件上传" )public Result<String> upload(MultipartFile file){log.info ( "文件上传,{}",file );try {String originalFilename = file.getOriginalFilename ();//获得文件原来的文件名称//截取原始文件名的后缀String extension = originalFilename.substring ( originalFilename.lastIndexOf ( "." ) );//创建新的文件名称String objectName = UUID.randomUUID ().toString () + extension;String filePath = aliOssUtil.upload ( file.getBytes (), objectName );return Result.success (filePath);} catch (IOException e) {log.error ( "文件上传失败,{}",e );}return Result.error ( "文件上传失败" );}}
2.3、新增菜品
1.DishController
/*** 新增菜品* @param dishDTO* @return*/@PostMapping@ApiOperation ( "新增菜品" )public Result save(@RequestBody DishDTO dishDTO){log.info ( "新增菜品,{}",dishDTO );dishService.saveWithFlavor (dishDTO);return Result.success ();}
2.DishServiceImlp
/*** 新增菜品和对应的口味* @param dishDTO*/@Transactional //注解方式的事务管理 操作多张表保证数据的原子性,一致性@Overridepublic void saveWithFlavor(DishDTO dishDTO) {Dish dish = new Dish ();BeanUtils.copyProperties ( dishDTO,dish );//向菜品表插入一条数据dishMapper.insert(dish);//获取Insert语句生成的主键值Long dishId = dish.getId ();//向口味表插入n条数据List<DishFlavor> flavors = dishDTO.getFlavors ();if (flavors !=null && flavors.size () >0){flavors.forEach ( dishFlavor -> dishFlavor.setDishId ( dishId ));//向口味表插入n条数据dishFlavorMapper.insertBatch(flavors);}
3.Mapper
import com.sky.annotation.AutoFill;
import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.enumeration.OperationType;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface DishMapper {/*** 根据分类id查询菜品数量* @param categoryId* @return*/@Select("select count(id) from dish where category_id = #{categoryId}")Integer countByCategoryId(Long categoryId);/*** 修改菜品信息* @param dishDTO*/void updateDish(DishDTO dishDTO);/*** 新增菜品* @param dish*/@AutoFill ( OperationType.INSERT )void insert(Dish dish);
}
import com.sky.entity.DishFlavor;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* @param flavors*/void insertBatch(List<DishFlavor> flavors);
}
4.XML
<insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into dish(id,name,category_id,price,image,description,status,create_time,update_time,create_user,update_user)values(#{id},#{name},#{categoryId},#{price},#{image},#{description},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})</insert>
<insert id="insertBatch">insert into dish_flavor (dish_id,name,value) values<foreach collection="flavors" item="df" separator=",">(#{df.dishId},#{df.name},#{df.value})</foreach></insert>
三、菜品分页查询
3.1、需求分析设计




3.2、代码实现
1.Controller
/*** 菜品分页查询* @param dishPageQueryDTO* @return*/@ApiOperation ( "菜品分页查询" )@GetMapping("/page")public Result<PageResult> dishPageQuery(DishPageQueryDTO dishPageQueryDTO){log.info ( "分页查询,{}",dishPageQueryDTO );PageResult pageResult= dishService.dishPageQuery(dishPageQueryDTO);return Result.success (pageResult);}
2.Service
/*** 菜品分页查询* @param dishPageQueryDTO* @return*/@ApiOperation ( "菜品分页查询" )@GetMapping("/page")public Result<PageResult> dishPageQuery(DishPageQueryDTO dishPageQueryDTO){log.info ( "分页查询,{}",dishPageQueryDTO );PageResult pageResult= dishService.dishPageQuery(dishPageQueryDTO);return Result.success (pageResult);}
3.Mapper
<!--分页查询--><select id="dishPageQuery" resultType="com.sky.vo.DishVO">select d.* ,c.name as categoryName from dish d left outer join category c on d.category_id = c.id<where><if test="name !=null"> and d.name like concat('%',#{name},'%')</if><if test="categoryId !=null">and d.category_id =#{categoryId}</if><if test="status !=null"> and d.status=#{status}</if></where>order by d.create_time desc</select>
四、删除菜品
4.1、需求分析与设计




4.2、代码实现
1.Controller层
/*** 批量删除菜品* @param ids* @return*/@DeleteMapping@ApiOperation ( "批量删除菜品" )public Result delete(@RequestParam List<Long> ids ){log.info ( "批量删除菜品,{}",ids );dishService.deleteBatch(ids);return Result.success ();}
2.Service层
/*** 批量删除* @param ids*/@Transactional@Overridepublic void deleteBatch(List<Long> ids) {//判断当前菜品是否能够删除--是否存在起售中的菜品??for (Long id : ids) {Dish dish=dishMapper.getById(id);if (dish.getStatus ()== StatusConstant.ENABLE){//当前菜品起售中,不能删除throw new DeletionNotAllowedException ( MessageConstant.DISH_ON_SALE );}}//判断当前菜品是否能够删除--当前菜品是否被套餐关联List<Long> setmealIds = setmealDishMapper.GetSetmealIdsByDishIds ( ids );if (setmealIds !=null && setmealIds.size ()>0){//当前菜品被套餐关联不能删除throw new DeletionNotAllowedException ( MessageConstant.DISH_BE_RELATED_BY_SETMEAL );}//删除菜品表中的菜品数据for (Long id : ids) {dishMapper.deleteById(id);//删除菜品关联的口味数据dishFlavorMapper.deleteByDishId(id);}}
3.Mapper层
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.SetmealDishMapper"><!--根据菜品ID查询套餐ID--><select id="GetSetmealIdsByDishIds" resultType="java.lang.Long">select setmeal_id from setmeal_dish where dish_id in<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">#{dishId}</foreach></select>
</mapper>
import com.sky.entity.DishFlavor;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* @param flavors*/void insertBatch(List<DishFlavor> flavors);/*** 根据菜品id删除对应的口味数据* @param dishId*/@Delete ( "delete from dish_flavor where dish_id=#{dishId}" )void deleteByDishId(Long dishId);
}
五、修改菜品
5.1、需求分析设计



5.2、根据ID查询菜品接口开发
service层
/*** 根据ID查询菜品信息及口味* @param id* @return*/@Transactional@Overridepublic DishVO getById(Long id) {Dish dish =dishMapper.getById ( id );List<DishFlavor> flavors = dishFlavorMapper.getFlavor(id);DishVO dishVO = new DishVO ();BeanUtils.copyProperties ( dish,dishVO );dishVO.setFlavors ( flavors );return dishVO;}
5.3、修改菜品接口开发
1.Controller层
/*** 修改菜品信息* @param dishDTO* @return*/@PutMapping@ApiOperation ( "修改菜品" )public Result updateDish(@RequestBody DishDTO dishDTO){log.info ( "修改菜品,{}",dishDTO );dishService.updateDish(dishDTO);return Result.success ();}
2.Service层
/*** 修改菜品* @param dishDTO*/@AutoFill ( value = OperationType.UPDATE)@Overridepublic void updateDish(DishDTO dishDTO) {//修改菜品基本信息Dish dish = new Dish ();BeanUtils.copyProperties ( dishDTO,dish );dishMapper.updateDish(dish);//删除原有的口味数据dishFlavorMapper.deleteByDishId (dishDTO.getId () );//重新插入口味数据List<DishFlavor> flavors = dishDTO.getFlavors ();if (flavors !=null && flavors.size ()>0){flavors.forEach ( dishFlavor ->{dishFlavor.setDishId ( dishDTO.getId () );} );dishFlavorMapper.insertBatch ( flavors );}}
3.Mapper层
<update id="updateDish">update dish<set><if test="categoryId !=null">category_id=#{categoryId},</if><if test="description !=null">description=#{description},</if><if test="id !=null">id =#{id},</if><if test="image !=null">image =#{image},</if><if test="name !=null">name =#{name},</if><if test="price !=null">price =#{price},</if><if test="status !=null">status=#{status}</if></set>where id=#{id}</update>
<insert id="insertBatch">insert into dish_flavor (dish_id,name,value) values<foreach collection="flavors" item="df" separator=",">(#{df.dishId},#{df.name},#{df.value})</foreach></insert>
/*** 根据菜品id删除对应的口味数据* @param dishId*/@Delete ( "delete from dish_flavor where dish_id=#{dishId}" )void deleteByDishId(Long dishId);
相关文章:
公共字段自动填充、菜品管理
一、公共字段填充 1.1、问题分析 1.2、实现思路 1.3、代码开发 1.3.1、自定义注解 import com.sky.enumeration.OperationType;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import jav…...
前端面试 面试多起来了
就在昨天 10.17 号,同时收到了三个同学面试的消息。他们的基本情况都是双非院校本科、没有实习经历、不会消息中间件和 Spring Cloud 微服务,做的都是单体项目。但他们投递简历还算积极,从今年 9 月初就开始投递简历了,到现在也有一个多月了。 来看看,这些消息。 为…...
Qt常见类名关系整理
1、QAbstractItemModel与QAbstractItemView 模型的基类: The QAbstractItemModel class provides the abstract interface for item model classes. Inherited By: QAbstractListModel,QAbstractProxyModel,and QAbstractTableModel 视图的基类: The QAbstractIte…...
YOLO8实战:yolov8实现行人跟踪计数
本篇文章首先介绍YOLOV8实现人流量跟踪计数的原理,文末附代码 引言:行人跟踪统计是智能监控系统中的重要功能,可以广泛应用于人流控制、安全监控等领域。传统的行人跟踪算法往往受到光照、遮挡等因素的干扰,难以实现准确跟踪。随着深度学习技术的发展,目标检测模型逐渐成为…...
shell脚本学习-2
文章目录 一、shell参数传递二、shell中的特殊变量三、shell中的函数四、shell函数中的参数 一、shell参数传递 运行 Shell 脚本文件时我们可以给它传递一些参数,这些参数在脚本文件内部可以使用$n的形式来接收,例如,$1 表示第一个参数&…...
web3:智能合约浏览器版本的 IDE - remix 使用教程
如果你是一位web3行业的从业者,那么智能合约一定是要接触的,这里我们就智能合约浏览器版本的 IDE-remix来介绍一下,及简单的使用操作 目录 Remix简介官方网址语言设置使用编辑合约编译合约部署合约测试验证Remix简介 Remix 是一个开源的 Solidity 智能合约开发环境,是一款…...
信号类型(通信)——QPSK、OQPSK、IJF_OQPSK调制信号
系列文章目录 《信号类型(通信)——仿真》 《信号类型(通信)——QAM调制信号》 文章目录 前言 一、QPSK通信调制信号 1.1、原理 1.2、仿真 二、OQPSK通信调制信号 1.1、原理 1.2、仿真 三、IJF_OQPSK通信调制信号 1.1、…...
常用压缩文件操作函数总结
常用压缩文件操作函数总结 1- 解压gz文件 gzip -d xx.gz 2- 函数 1 打开文件 函数名: gzopen 功能描述: 打开名为file的gz文件 参数: file:文件名 mode:打开模式 r 返回值: 打开的gz文件描述符 gzFile gzopen(const char *file, const char…...
leetcode_274 H指数
1. 题意 在数组中找到最大的k, 使得至少k个数不小于k。 H指数 2. 题解 2.1 排序 从大到小排序完后,直接模拟即可。 class Solution { public:int hIndex(vector<int>& citations) {sort( citations.begin(), citations.end() );int res 0;int cur …...
微服务框架Consul--新手入门
Consul Consul 是由 HashiCorp 开发的一款软件工具,提供了一组功能,用于服务发现、配置管理和网络基础设施自动化。它旨在帮助组织管理现代分布式和微服务架构系统的复杂性。以下是Consul的一些关键方面和功能: 服务发现:Consul …...
docker运行syslog-ng,搭建日志服务器
Splunk 的数据很多是用syslog-ng 来收集的。 使用docker 来搭建syslog-ng 服务器还是很方便的。 #create network docker network create -d macvlan --subnet=192.7.0.0/16 --gateway=192.7.0.1 -o parent=ens35 docker-out docker network create -d macvlan --ipv6 --sub…...
Redis代替session实现用户验证
一、Redis代替session实现用户验证。 下图是session的实现登录需要实现的代码模块,虽然可以实现完整功能,但是仍然存在一些问题。 在以往使用session当作用户验证的过程中,会有session共享的问题,每次承担请求的tomcat是不一样…...
Ubuntu 内核降级到指定版本
reference https://www.cnblogs.com/leebri/p/16786685.html 前往此网站,找到所需的内核 https://kernel.ubuntu.com/~kernel-ppa/mainline/ 查看系统架构 dpkg --print-architecture 二、下载安装包 注意:下载除lowlatency以外的deb包 三、安装内核 3…...
uniapp开发app,在ios真机上出现的css样式问题
比如下面的问题,在iphone 13上出现,在iphone xR上正常。 问题一:border:1rpx造成边框显示不全 在iphone13上border边框有一部分不显示: 在iphone xR上显示正常: 解决办法是: 将border边框设置中的1rpx改…...
uniapp 页面间传参方法
页面之间传参大概可分为以下几种情况: 上级页面 → 下级页面(单向)上级页面 ← 下级页面(单向)上级页面 ↔ 下级页面(双向) 一、上级页面 → 下级页面(单向) uni.naviga…...
【年终特惠】基于最新导则下生态环评报告编制技术暨报告篇、制图篇、指数篇、综合应用篇系统性实践技能提升
根据生态环评内容庞杂、综合性强的特点,依据生态环评最新导则,将内容分为4大篇章(报告篇、制图篇、指数篇、综合篇)、10大专题(生态环评报告编制、土地利用图的制作、植被类型及植被覆盖度图的制作、物种适宜生境分布图的制作、生物多样性测定、生物量及…...
驱动开发7 基于GPIO子系统编写LED驱动,编写应用程序进行测试设置定时器,5秒钟打印一次hello world
驱动代码 #include <linux/init.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/gpio.h> #include <linux/timer.h> #include <linux/of_irq.h> #include <linux/interrupt.h…...
亚马逊云科技为奇点云打造全面、安全、可扩展的数据分析解决方案
刘莹奇点云联合创始人、COO:伴随云计算的发展,数据技术也在快速迭代,成为客户迈入DT时代、实现高质量发展的关键引擎。我们很高兴能和云计算领域的领跑者亚马逊云科技一同,不断为客户提供安全可靠的产品与专业的服务。 超过1500家…...
应用案例|基于三维机器视觉的曲轴自动化上下料应用方案
Part.1 项目背景 此案例服务对象为国内某知名大型汽车零部件制造工厂,该工厂有针对曲轴工件的自动化上下料需求。由于之前来料码放不规范,工件无序散乱摆放,上料节拍要求高,该工厂上下料效率极低。 Part.2 传统曲轴上下料存在的缺…...
关于ios和Android手机的下载pdf文件功能探讨
现象 在工作中遇到了一个需求,在app中需要对一些协议(pdf格式的)进行下载,实现方法创建a标签,设置href的值为下载地址,设置download属性,调用a标签的点击事件进行下载,在Android手机中是调起默认浏览器的下载功能(正常现象,可以实现功能),但是在ios手机中是直接进行文件的有预…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...
【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项
一、条形码识别改名使用教程 打开软件并选择处理模式:打开软件后,根据要处理的文件类型,选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件,就选择 “PDF 识别模式”;若是处理图片文件&…...
基于Python的气象数据分析及可视化研究
目录 一.🦁前言二.🦁开源代码与组件使用情况说明三.🦁核心功能1. ✅算法设计2. ✅PyEcharts库3. ✅Flask框架4. ✅爬虫5. ✅部署项目 四.🦁演示效果1. 管理员模块1.1 用户管理 2. 用户模块2.1 登录系统2.2 查看实时数据2.3 查看天…...
