苍穹外卖04 (新增内表的外键id获取,多表分页查询,多表批量删除,修改先查在改内表外键id用主表的,起售时包含了“停售”状态的外关联表)

1. 新增套餐

1 需求分析和设计

业务规则:

  • 套餐名称唯一

  • 套餐必须属于某个分类

  • 套餐必须包含菜品

  • 名称、分类、价格、图片为必填项

  • 添加菜品窗口需要根据分类类型来展示菜品

  • 新增的套餐默认为停售状态

2 代码实现

1 根据分类id查询菜品

java 复制代码
DishController

@GetMapping("/list")
@ApiOperation("根据分类id查询菜品列表")
public Result queryDishesByCategoryId(Long categoryId){
    return dishService.queryDishesByCategoryId(categoryId);
}


----------------
DishService

/**
 * 根据分类id查询菜品列表
 * @param categoryId 分类id
 * @return categoryId对应的菜品列表
 */
Result queryDishesByCategoryId(Long categoryId);

----------------
DishServiceImpl

@Override
public Result queryDishesByCategoryId(Long categoryId) {
    List<Dish> dishes = dishMapper.selectByCategoryId(categoryId);
    return Result.success(dishes);
}

----------------
DishMapper

@Select("select * from dish where category_id = #{categoryId}")
List<Dish> selectByCategoryId(Long categoryId);

2 新增套餐

java 复制代码
SetmealController

package com.sky.controller.admin;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Api(tags = "套餐管理相关接口")
@RequestMapping("/admin/setmeal")
public class SetmealController {
    @Autowired
    private SetmealService setmealService;

    @PostMapping
    @ApiOperation("新增套餐")
    public Result addSetmeal(@RequestBody SetmealDTO dto){
        return setmealService.addSetmeal(dto);
    }
}


-----------------
SetmealService

package com.sky.service;
import com.sky.dto.SetmealDTO;
import com.sky.result.Result;
import java.util.List;

public interface SetmealService {
    Result addSetmeal(SetmealDTO dto);

}

-----------------
SetmealServiceImpl

package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.dto.SetmealDTO;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.SetmeatlDishMapper;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.SetmealService;
import com.sky.vo.SetmealVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
@Service
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmeatlDishMapper setmealDishMapper;

    @Override
    @Transactional
    public Result addSetmeal(SetmealDTO dto) {
        //1. 保存套餐
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(dto, setmeal);
        setmealMapper.insert(setmeal);
        //2. 保存套餐里关联的菜品
        List<SetmealDish> setmealDishes = dto.getSetmealDishes();
        if (setmealDishes != null && setmealDishes.size() > 0) {
            setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmeal.getId()));
            setmealDishMapper.batchInsert(setmealDishes);
        }
        return Result.success();
    }
}


-----------------
SetmealMapper

/**
     * 新增套餐
     * @param setmeal
     */
@AutoFill(OperationType.INSERT)
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("insert into setmeal(category_id, name, price, status, description, image, create_time, update_time, create_user, update_user) " +
        "        values (#{categoryId},#{name},#{price},#{status},#{description},#{image},#{createTime},#{updateTime},#{createUser},#{updateUser})")
void insert(Setmeal setmeal);

-------------------
SetmeatlDishMapper

void batchInsert(List<SetmealDish> setmealDishes);

----------------
SetmeatlDishMapper.xml

<insert id="batchInsert">
    insert into setmeal_dish (setmeal_id, dish_id, name, price, copies) values
    <foreach collection="setmealDishes" item="sd" separator=",">
        (#{sd.setmealId}, #{sd.dishId}, #{sd.name}, #{sd.price}, #{sd.copies})
    </foreach>
</insert>

2. 套餐分页查询

1 需求分析和设计

业务规则:

  • 根据页码进行分页展示

  • 每页展示10条数据

  • 可以根据需要,按照套餐名称、分类、售卖状态进行查询

2 代码实现

java 复制代码
SetmealController

@GetMapping("/page")
@ApiOperation("分页查询套餐")
public Result querySetmealsByPage(SetmealPageQueryDTO dto){
    return setmealService.querySetmealsByPage(dto);
}

----------------
SetmealService

/**
     * 分页查询套餐
     * @param dto
     * @return
     */
Result querySetmealsByPage(SetmealPageQueryDTO dto);

----------------
SetmealServiceImpl

@Override
public Result querySetmealsByPage(SetmealPageQueryDTO dto) {
    //1. 开启分页
    PageHelper.startPage(dto.getPage(), dto.getPageSize());
    //2. 查询列表
    Page<SetmealVO> page = setmealMapper.selectByPage(dto);
    //3. 封装结果
    PageResult pageResult = new PageResult(page.getTotal(), page.getResult());
    return Result.success(pageResult);
}

--------------
SetmealMapper

/**
     * 分页查询套餐列表
     * @param dto
     * @return
     */
Page<SetmealVO> selectByPage(SetmealPageQueryDTO dto);

--------------
SetmealMapper.xml

<?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.SetmealMapper">
    <select id="selectByPage" resultType="com.sky.vo.SetmealVO">
        select s.*, c.name categoryName from setmeal s left join category c on s.category_id = c.id
        <where>
            <if test="name!=null and name.length()>0">
                and s.name like concat('%', #{name}, '%')
            </if>
            <if test="categoryId!=null">
                and s.category_id = #{categoryId}
            </if>
            <if test="status!=null">
                and s.status = #{status}
            </if>
        </where>
        order by s.create_time desc
    </select>
</mapper>

3. 删除套餐

1 需求分析和设计

业务规则:

  • 可以一次删除一个套餐,也可以批量删除套餐

  • 起售中的套餐不能删除

2 代码实现

java 复制代码
SetmealController

@DeleteMapping
@ApiOperation("删除套餐")
public Result batchDeleteSetmealsByIds(@RequestParam List<Long> ids){
    return setmealService.batchDeleteSetmealsByIds(ids);
}

----------
SetmealService

/**
     * 批量删除套餐
     * @param ids
*/
Result batchDeleteSetmealsByIds(List<Long> ids);

----------
SetmealServiceImpl

@Override
@Transactional
public Result batchDeleteSetmealsByIds(List<Long> ids) {
    //1. 如果有某个套餐是"起售"状态,则不允许删除
    int count = setmealMapper.selectEnableSetmealsCount(ids);
    if (count > 0) {
        throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
    }
    //2. 删除套餐
    setmealMapper.batchDeleteByIds(ids);
    //3. 删除套餐关联的菜品
    setmealDishMapper.batchDeleteBySetmealIds(ids);
    return Result.success();
}

-----------
SetmealMapper

/**
     * 查询 ids对应的套餐中,起售状态的套餐 数量
     * @param ids
     * @return
     */
int selectEnableSetmealsCount(List<Long> ids);

/**
     * 根据ids批量删除套餐
     * @param ids
     */
void batchDeleteByIds(List<Long> ids);

------------
SetmealMapper.xml

<select id="selectEnableSetmealsCount" resultType="int">
    select count(*) from setmeal where status = 1 and
    <foreach collection="ids" item="id" separator="," open="id in(" close=")">
        #{id}
    </foreach>
</select>

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

---------------
SetmeatlDishMapper

    /**
     * 根据套餐ids,批量删除这些套餐包含的菜品关联关系
     * @param ids
     */
void batchDeleteBySetmealIds(List<Long> ids);

-----------
SetmeatlDishMapper.xml

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

4. 修改套餐

1 需求分析和设计

接口设计(共涉及到5个接口):

  • 根据id查询套餐

  • 根据类型查询分类(已完成)

  • 根据分类id查询菜品(已完成)

  • 图片上传(已完成)

  • 修改套餐

2 代码实现

1 根据id查询套餐

java 复制代码
SetmealController

@GetMapping("/{id}")
@ApiOperation("根据id查询套餐")
public Result querySetmealById(@PathVariable("id") Long id) {
    return setmealService.querySetmealById(id);
}


----------
SetmealService

/**
 * 根据id查询套餐
 * @param id
 * @return
 */
Result querySetmealById(Long id);

-----------
SetmealServiceImpl

@Override
public Result querySetmealById(Long id) {
    //查询套餐信息
    Setmeal setmeal = setmealMapper.selectById(id);
    //查询套餐关联的菜品列表
    List<SetmealDish> setmealDishes = setmealDishMapper.selectBySetmealId(id);
    //封装成VO对象
    SetmealVO vo = new SetmealVO();
    BeanUtils.copyProperties(setmeal, vo);
    vo.setSetmealDishes(setmealDishes);
    return Result.success(vo);
}

----------
SetmealMapper

/**
 * 根据id查询套餐
 * @param id
 * @return
 */
@Select("select * from setmeal where id = #{id}")
Setmeal selectById(Long id);

----------
SetmeatlDishMapper

/**
 * 根据套餐id,查询套餐内包含的菜品
 * @param setmealId
 * @return
 */
@Select("select * from setmeal_dish where setmeal_id = #{setmealId}")
List<SetmealDish> selectBySetmealId(Long setmealId);

2 修改套餐

java 复制代码
SetmealController

@PutMapping
@ApiOperation("修改套餐")
public Result updateSetmeal(@RequestBody SetmealDTO dto){
    return setmealService.updateSetmeal(dto);
}


----------
SetmealService

/**
 * 修改套餐
 * @param dto
 * @return
 */
Result updateSetmeal(SetmealDTO dto);

----------
SetmealServiceImpl

@Override
@Transactional
public Result updateSetmeal(SetmealDTO dto) {
    //1. 修改套餐
    Setmeal setmeal = new Setmeal();
    BeanUtils.copyProperties(dto, setmeal);
    setmealMapper.updateById(setmeal);
    //2. 修改套餐关联的菜品
    //2.1 删除套餐 之前关联的菜品
    setmealDishMapper.batchDeleteBySetmealIds(Collections.singletonList(dto.getId()));
    //2.2 重新添加 关联的菜品
    List<SetmealDish> setmealDishes = dto.getSetmealDishes();
    if (setmealDishes != null && setmealDishes.size() > 0) {
        setmealDishes.forEach(setmealDish -> setmealDish.setSetmealId(setmeal.getId()));
        setmealDishMapper.batchInsert(setmealDishes);
    }
    return Result.success();
}

-----------
SetmealMapper

/**
 * 根据id修改套餐
 * @param setmeal
 */
@AutoFill(OperationType.UPDATE)
void updateById(Setmeal setmeal);

-----------
SetmealMapper.xml

<update id="updateById">
    UPDATE setmeal
    <set>
        <if test="categoryId!=null">category_id = #{categoryId},</if>
        <if test="name!=null and name.length()>0">name = #{name},</if>
        <if test="price!=null">price = #{price},</if>
        <if test="status!=null">status = #{status},</if>
        <if test="description!=null and description.length()>0">description = #{description},</if>
        <if test="image!=null and image.length()>0">image = #{image},</if>
        <if test="updateTime!=null">update_time = #{updateTime},</if>
        <if test="updateUser!=null">update_user = #{updateUser}</if>
    </set>
    WHERE id = #{id}
</update>

5. 起售停售套餐

1 需求分析和设计

业务规则:

  • 可以对状态为起售的套餐进行停售操作,可以对状态为停售的套餐进行起售操作

  • 起售的套餐可以展示在用户端,停售的套餐不能展示在用户端

  • 起售套餐时,如果套餐内包含停售的菜品,则不能起售

2 代码实现

java 复制代码
SetmealController

@PostMapping("/status/{status}")
@ApiOperation("启用禁用套餐")
public Result updateStatus(@PathVariable("status") Integer status, Long id){
    return setmealService.updateStatus(id, status);
}


--------------
SetmealService

/**
     * 套餐起售、停售
     * @param status
     * @param id
*/
Result updateStatus(Long id, Integer status);


-------------
SetmealServiceImpl

@Autowired
private DishMapper dishMapper;

@Override
public Result updateStatus(Long id, Integer status) {
    //起售套餐时,如果包含了"停售"状态的菜品,则不允许起售
    if (StatusConstant.ENABLE.equals(status)) {
        //查询套餐关联的所有菜品
        List<Dish> dishes = dishMapper.selectBySetmealId(id);
        //如果有任意一个菜品是"停售"状态,就抛出异常
        long count = dishes.stream()
            .filter(dish -> dish.getStatus().equals(StatusConstant.DISABLE))
            .count();
        if (count > 0) {
            throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
        }
    }

    //起售/停售套餐
    Setmeal setmeal = Setmeal.builder()
        .id(id)
        .status(status)
        .build();
    setmealMapper.updateById(setmeal);
    return Result.success();
}


-----------
DishMapper

/**
     * 根据套餐id查询菜品
     * @param setmealId
     * @return
*/
@Select("select * from dish where id in(select dish_id from setmeal_dish where setmeal_id = #{setmealId})")
List<Dish> selectBySetmealId(Long setmealId);
相关推荐
P.H. Infinity15 分钟前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天18 分钟前
java的threadlocal为何内存泄漏
java
caridle30 分钟前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^35 分钟前
数据库连接池的创建
java·开发语言·数据库
苹果醋339 分钟前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花43 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端1 小时前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan1 小时前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
全栈开发圈1 小时前
新书速览|Java网络爬虫精解与实践
java·开发语言·爬虫