苍穹外卖day03-----菜品管理

一.公共字段自动填充

1.需求分析

因为公共字段过多会出现代码冗余,不便于维护的问题,所以我们通过想办法为其设置自动填充。

实现思路

2.代码实现

二.新增菜品

1.需求分析

产品原型

业务规则

接口设计

数据库设计

2.代码实现

1.文件上传

controller层实现文件上传,需要调用aliOssUtil工具类,那么就需要创建这个工具类对象,接着我们就应该想办法为这个对象传递参数,想要传递参数,我们想到了IOC容器的自动注入,这里我们使用了一个配置类讲AliOssUtil工具类对象交给IOC容器,然后直接在controller层自动注入即实现了文件上传的功能。

yml配置文件

复制代码
  alioss:
    endpoint: ${sky.alioss.endpoint}   //访问域名
    access-key-id: ${sky.alioss.access-key-id}  //访问密钥id
    access-key-secret: ${sky.alioss.access-key-secret}   //访问密钥密码
    bucket-name: ${sky.alioss.bucket-name}  //存储桶名称

  alioss:
    endpoint: oss-cn-beijing.aliyuncs.com
    access-key-id: your-access-key-id
    access-key-secret: your-access-key-secret
    bucket-name: your-bucket-name

controller

复制代码
@RestController
@Slf4j
@Api("文件上传")
@RequestMapping("/admin/common")
public class CommonController {
    @Autowired
    private AliOssUtil aliOssUtil;
    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(MultipartFile file){
        log.info("文件上传:{}",file);
        try {
            String originalFilename = file.getOriginalFilename();
            String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
            String objectName = UUID.randomUUID().toString() + substring;
            String filePath = aliOssUtil.upload(file.getBytes(), objectName);
            return Result.success(filePath);
        } catch (Exception e) {
            log.error("文件失败的原因:{}",e);
        }
        return Result.error(MessageConstant.UPLOAD_FAILED);
    }
}

配置类

复制代码
package com.sky.config;

import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class OssConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
        log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);
        return new AliOssUtil(aliOssProperties.getEndpoint(),
                aliOssProperties.getAccessKeyId(),
                aliOssProperties.getAccessKeySecret(),
                aliOssProperties.getBucketName());
    }
}

2.新增菜品

controller

复制代码
package com.sky.controller.admin;

import com.sky.dto.DishDTO;
import com.sky.result.Result;
import com.sky.service.DishService;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/admin/dish")
@Slf4j
public class DishController {
    @Autowired
    private DishService dishService;
    @PostMapping
    public Result saveWithFlavor(@RequestBody DishDTO dishDTO){
        log.info("新增菜品:{}",dishDTO);
        dishService.saveWithFlavor(dishDTO);
        return Result.success();
    }
}

service

复制代码
@Service
@Slf4j
public class DishServiceIml implements DishService {
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Override
    @Transactional
    public void saveWithFlavor(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dish.setCreateTime(LocalDateTime.now());
        dish.setUpdateTime(LocalDateTime.now());
        dish.setCreateUser(BaseContext.getCurrentId());
        dish.setUpdateUser(BaseContext.getCurrentId());
        //新增菜品
        dishMapper.saveWithFlavor(dish);
        Long dishId = dish.getId();
        //新增口味
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if(flavors != null && !flavors.isEmpty()){
            flavors.forEach(dishFlavor -> {
                dishFlavor.setDishId(dishId);
            });
            dishFlavorMapper.saveWithFlavor(flavors);
        }
    }
}

mapper

复制代码
@Mapper
public interface DishMapper {

    /**
     * 根据分类id查询菜品数量
     * @param categoryId
     * @return
     */
    @Select("select count(id) from dish where category_id = #{categoryId}")
    Integer countByCategoryId(Long categoryId);

    void saveWithFlavor(Dish dish);
}

<?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.DishMapper">
    <insert id="saveWithFlavor" useGeneratedKeys="true" keyProperty="id">
        insert into dish (name, category_id, price, image, description, create_time, update_time, create_user,
        update_user, status)
        values (#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser},
        #{updateUser}, #{status})
    </insert>
</mapper>

@Mapper
public interface DishFlavorMapper {
    void saveWithFlavor(List<DishFlavor> flavors);
}

<?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.DishFlavorMapper">

    <insert id="saveWithFlavor">
        insert into dish_flavor (dish_id, name, value) VALUES
        <foreach collection="flavors" item="df" separator=",">
            (#{df.dishId},#{df.name},#{df.value})
        </foreach>
    </insert>
</mapper>

三.菜品分页查询

1.需求分析

产品原型

业务规则

接口设计

2.代码实现

controller

复制代码
    @GetMapping("/page")
    @ApiOperation("分页查询")
    public Result<PageResult> pageQuery(DishPageQueryDTO dishPageQueryDTO){
        log.info("分页查询:{}",dishPageQueryDTO);
        PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
        return Result.success(pageResult);
    }

service

复制代码
 @Override
    public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
        Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
        return new PageResult(page.getTotal(),page.getResult());
    }

mapper

复制代码
Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);

<select id="pageQuery" 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>

四.删除菜品

1.需求分析

产品原型

业务规则

接口设计

数据库设计

2.代码实现

controller

复制代码
 @DeleteMapping
    @ApiOperation("删除菜品")
    public Result delete(@RequestParam List<Long> ids){
        log.info("删除菜品:{}",ids);
        dishService.deleteBatch(ids);
        return Result.success();
    }

service

复制代码
 @Override
    public void deleteBatch(List<Long> ids) {
        //菜品是否起售,不满足条件则不能删除
        for (Long id :ids) {
            Dish dish = dishMapper.select(id);
            Object setmealDishId = setmealDishMapper.selectById(id);
            if (dish.getStatus() == StatusConstant.ENABLE) {
                throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
            }
        }
        //菜品是否与套餐关联
        for (Long id :ids) {
            Object setmealDishId = setmealDishMapper.selectById(id);
            if (setmealDishId != null) {
                throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
            }
        }
        //如果可以删除口味数据一并删除
       for (Long id :ids){
           dishMapper.delete(id);
           dishFlavorMapper.delete(id);
       }
    }

mapper

复制代码
@Select("select * from dish where id = #{id}")
    Dish select(Long id);

package com.sky.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface SetmealDishMapper {
    @Select("select setmeal_id from setmeal_dish where dish_id = #{id}")
    Object selectById(Long id);

    void delete(List<Long> ids);
}

<?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">

    <delete id="delete">
        delete from setmeal_dish where setmeal_id in
        <foreach collection="ids" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </delete>
</mapper>

五.修改菜品

1.需求分析

产品原型

接口设计

要想实现更新操作,我们应该先查询回显,然后update。

因为这里涉及多表查询,所以我们有两个思路,一个是外连接,一个是两次查询,这里我们使用两次查询的方法。

查询回显结束之后,我们如何实现更新呢。我们依旧采取分别更新的方法进行更新。

首先对dish进行更新。

那么到了对flavors进行更新的时候,因为flavor的数量可能增多或减少,所以这里不建议直接更新,那么我们该怎么呢?我们可以先删除后增加以实现修改的效果

2.代码实现

controller

复制代码
 @PutMapping
    @ApiOperation("修改菜品")
    public Result updateById(@RequestBody DishDTO dishDTO){
        log.info("修改菜品:{}",dishDTO);
        dishService.updateById(dishDTO);
        return Result.success();
    }

service

复制代码
/**@Override
    public void updateById(DishDTO dishDTO) {
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dish.setUpdateTime(LocalDateTime.now());
        dish.setUpdateUser(BaseContext.getCurrentId());
        //修改菜品
        dishMapper.updateById(dish);
        //修改口味
        dishFlavorMapper.delete(dishDTO.getId());
        if(!dishDTO.getFlavors().isEmpty()){
            dishDTO.getFlavors().forEach(flavor -> {
                flavor.setDishId(dishDTO.getId());
            });
            dishFlavorMapper.saveWithFlavor(dishDTO.getFlavors());
        }
    }

mapper

复制代码
 @Update("UPDATE dish SET name = #{name}, category_id = #{categoryId}, price = #{price}, image = #{image}, description = #{description}, status = #{status}, update_time = #{updateTime}, update_user = #{updateUser} WHERE id = #{id}")
    void updateById(Dish dish);
相关推荐
NE_STOP2 小时前
MyBatis-配置文件解读及MyBatis为何不用编写Mapper接口的实现类
java
数据组小组3 小时前
免费数据库管理工具深度横评:NineData 社区版、Bytebase 社区版、Archery,2026 年开发者该选哪个?
数据库·测试·数据库管理工具·数据复制·迁移工具·ninedata社区版·naivicat平替
南果梨5 小时前
OpenClaw 完整教程!从安装到使用(官方脚本版)
前端·git·开源
后端AI实验室7 小时前
用AI写代码,我差点把漏洞发上线:血泪总结的10个教训
java·ai
程序员清风8 小时前
小红书二面:Spring Boot的单例模式是如何实现的?
java·后端·面试
belhomme9 小时前
(面试题)Redis实现 IP 维度滑动窗口限流实践
java·面试
Be_Better9 小时前
学会与虚拟机对话---ASM
java
悟空聊架构9 小时前
基于KaiwuDB在游乐场“刷卡+投币”双模消费系统中的落地实践
数据库·后端·架构
IvorySQL9 小时前
PostgreSQL 技术日报 (3月4日)|硬核干货 + 内核暗流一网打尽
数据库·postgresql·开源
开源之眼11 小时前
《github star 加星 Taimili.com 艾米莉 》为什么Java里面,Service 层不直接返回 Result 对象?
java·后端·github