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

苍穹外卖项目demo开发day3 公共字段自动填充 增删改查菜品

公共字段自动填充 技术点 枚举 自定义注解 AOP切面 反射

/**
 * 自定义注解 用于标识某个方法需要进行功能字段自动填充处理
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ChengoAutoFill {
    //数据库操作类型 UPDATE INSERT
    OperationType value();
}

/**
 * 自定义切面 实现公共字段自动填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class ChengoAutoFillAspect {

    /**
     * 切入点 拦截insert和update操作
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.ChengoAutoFill)")
    public void autoFillPointCut(){}



    /**
     * 前置通知 在通知中尽显公共字段的赋值
     * @param joinPoint
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始进行公共字段自动填充....");
        //获取当前被拦截的方法上的数据库操作类型 反射操作
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
        ChengoAutoFill autoFill = signature.getMethod().getAnnotation(ChengoAutoFill.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 setCreateTime = entity.getClass().getDeclaredMethod(SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(SET_UPDATE_USER, Long.class);

                //通过反射为对象属性赋值
                setCreateUser.invoke(entity,currentId);
                setUpdateUser.invoke(entity,currentId);
                setCreateTime.invoke(entity,now);
                setUpdateTime.invoke(entity,now);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        } else if (operationType == OperationType.UPDATE) {
            //两个公共字段赋值 修改时间和修改人
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(SET_UPDATE_USER, Long.class);

                //通过反射为对象属性赋值
                setUpdateUser.invoke(entity,currentId);
                setUpdateTime.invoke(entity,now);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

Mapper里上自定义注解
    @ChengoAutoFill(value = OperationType.UPDATE)
    void update(Employee employee);

    @ChengoAutoFill(value = OperationType.INSERT)
    void insert(Employee employee);


增菜品

上传文件需要阿里云oss 配置好自己的信息 写好yml和上传内容即可

/**
 * 配置类 用于创建AliOssUtil对象
 */
@Configuration
@Slf4j
public class OssConfiguration {
    @Bean
    @ConditionalOnMissingBean//只创建一个bean 确保程序启动过程中只有一个bean
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
        return new AliOssUtil(
                aliOssProperties.getEndpoint(),
                aliOssProperties.getAccessKeyId(),
                aliOssProperties.getAccessKeySecret(),
                aliOssProperties.getBucketName()
        );
    }
}
控制层
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {
    @Autowired
    private AliOssUtil aliOssUtil;
    /**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(@RequestBody MultipartFile file){
        log.info("文件上传:{}",file);
        try {
            //取出原始文件名
            String originalFilename = file.getOriginalFilename();
            //截取原始文件名的后缀 。。。。.png .jpg
            String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
            //构建新文件名称
            String objectName = UUID.randomUUID().toString() + substring;
            //文件请求连接
            String filePath = aliOssUtil.upload(file.getBytes(), objectName);
            return Result.success(filePath);
        } catch (IOException e) {
            log.error("文件上传失败:{}",e);
        }
        return Result.error(MessageConstant.UPLOAD_FAILED);
    }
}

上面是怎么上传文件 下面的新增菜品让我烦了好长一段时间 总结经验 不能边看边敲 需要看明白再回来思考 并自己先敲

这个问题折腾了我一个小时 第二次犯了 sql语句写的封装类对象里不能用下划线 并且必须驼峰命名

查询

这里有个VO设计

在这个模块上花了三个小时左右,, 就是因为我服务器太久没动宕机了 很崩溃 不想做了

还是继续做吧‘、、、、、、、、、、

删除菜品

     控制层
     /**
     * 菜品批量删除
     * @param ids
     * @return
     */
    @DeleteMapping
    @ApiOperation("菜品批量删除")
    public Result delete(@RequestParam List<Long> ids){
        log.info("菜品批量删除:{}",ids);
        dishService.deleteBatch(ids);
        return Result.success();
    }
    


@Mapper  持久层
public interface SetmealDishMapper {
    /**
     * 根据菜品id查找套餐id
     * @param dishIds
     * @return
     */

    List<Long> getSetmealIdsByDishIds(List<Long> dishIds);

}



    业务实现层
    /**
     * 菜品批量删除
     * @param ids
     */
    @Override
    public 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> setmealIdsByDishIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
        if(setmealIdsByDishIds != null && setmealIdsByDishIds.size() > 0){
            //当前菜品被套餐关联 不能删除
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }
        //删除菜品表中的菜品数据
        for (Long id : ids) {
            dishMapper.deleteById(id);
            //删除口味表里的口味数据
            dishFlavorMapper.deleteById(id);
        }




    要删除菜品与其连带的口味数据
    /**
     * 根据id主键删菜品
     * @param id
     */
    @Delete("delete from dish where id = #{id};")
    void deleteById(Long id);
    /**
     * 根据菜品id来删口味数据
     * @param dishIds
     */
    @Delete("delete from dish_flavor where dish_id = #{dishIds}")
    void deleteById(Long dishIds);

改菜品

根据id查询菜品 需要分两次查询 第一次查询dish菜品 第二次查询菜品关联的口味

    业务层
    /**
     * 根据id查询菜品和对应的口味数据
     * @param id
     * @return
     */
    @Override
    public DishVO getByIdWithFlavor(Long id) {
        //根据id查询菜品数据
        Dish dish = dishMapper.getById(id);
        //根据菜品id查询口味数据
        List<DishFlavor> dishFlavors = dishFlavorMapper.getByDishId(id);
        //把查询到的数据封装到VO
        DishVO dishVO = new DishVO();
        BeanUtils.copyProperties(dish,dishVO);
        dishVO.setFlavors(dishFlavors);

        return dishVO;
    }
    *************************************************
    接口层
    /**
     * 根据id查询菜品和对应的口味数据
     * @param id
     * @return
     */
    DishVO getByIdWithFlavor(Long id);
    *************************************************
    控制层
    @GetMapping("/{id}")
    @ApiOperation("根据id查询菜品·")
    public Result<DishVO> getById(@PathVariable Long id){
        log.info("根据id查询菜品:{}",id);
        DishVO dishVO = dishService.getByIdWithFlavor(id);
        return Result.success(dishVO);
    }
    *************************************************
    Mapper层
    /**
     * 根据菜品id查询口味数据
     * @param dishId
     * @return
     */
    @Select("select * from dish_flavor where dish_id = #{dishId}")
    List<DishFlavor> getByDishId(Long dishId);
    /**
     * 查询菜品
     * @param id
     * @return
     */
    @Select("select * from dish where id = #{id}")
    Dish getById(Long id);

 在这写修改的时候 把控制层的内容写到实体类里了,, 还好发现了

继续加油

相关文章:

  • 使用llama.cpp在gpu和cpu上运行deepseek-r1 7b的性能对比
  • 计算机组成原理—— 总线系统(十二)
  • pytest测试专题 - 2.1 一种推荐的测试目录结构
  • 编程速递-庆祝Delphi诞生30周年!
  • 2025智能硬件售后服务管理系统选择的六大标准
  • 小项目第一天
  • CAS单点登录(第7版)20.用户界面
  • Centos安装php-8.0.24.tar
  • unity学习41:动画里的曲线curve参数 和 事件 events
  • CAS单点登录(第7版)17.账户注册
  • 深度学习框架探秘|TensorFlow:AI 世界的万能钥匙
  • 安科瑞光伏发电防逆流解决方案——守护电网安全,提升能源效率
  • 算法随笔_51: 表现良好的最长时间段_方法2
  • Java三大特性
  • Uniapp 短视频去水印解析工具开发实现
  • Ubuntu添加桌面快捷方式
  • 2025有哪些关键词优化工具好用
  • XML Schema anyAttribute 元素详解
  • 算法12-贪心算法
  • 解析浏览器中JavaScript与Native交互原理:以WebGPU为例
  • 印度外交秘书:“朱砂行动”不针对军事设施,无意升级事态
  • 本科生已发14篇SCI论文被指由其教授父亲挂名,重庆大学成立工作组核实
  • 5月12日至13日北京禁飞“低慢小”航空器
  • 广州下调个人住房公积金贷款利率
  • 司法部:持续规范行政执法行为,加快制定行政执法监督条例
  • 酒店取消订单加价卖何以屡禁不绝?专家建议建立黑名单并在商家页面醒目标注