|
|
@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
package com.sky.service.impl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.github.pagehelper.Page;
|
|
|
|
|
|
|
|
import com.github.pagehelper.PageHelper;
|
|
|
|
|
|
|
|
import com.sky.constant.MessageConstant;
|
|
|
|
|
|
|
|
import com.sky.constant.StatusConstant;
|
|
|
|
|
|
|
|
import com.sky.dto.DishDTO;
|
|
|
|
|
|
|
|
import com.sky.dto.DishPageQueryDTO;
|
|
|
|
|
|
|
|
import com.sky.entity.Dish;
|
|
|
|
|
|
|
|
import com.sky.entity.DishFlavor;
|
|
|
|
|
|
|
|
import com.sky.entity.Setmeal;
|
|
|
|
|
|
|
|
import com.sky.entity.SetmealDish;
|
|
|
|
|
|
|
|
import com.sky.exception.DeletionNotAllowedException;
|
|
|
|
|
|
|
|
import com.sky.mapper.DishMapper;
|
|
|
|
|
|
|
|
import com.sky.result.PageResult;
|
|
|
|
|
|
|
|
import com.sky.service.DishService;
|
|
|
|
|
|
|
|
import com.sky.vo.DishVO;
|
|
|
|
|
|
|
|
import com.sky.vo.SetmealVO;
|
|
|
|
|
|
|
|
import io.swagger.annotations.ApiOperation;
|
|
|
|
|
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
|
|
import org.springframework.context.annotation.Bean;
|
|
|
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
|
|
|
|
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
|
|
import java.util.Collections;
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* DishServiceImpl类,实现了DishService接口,作为业务逻辑层的实现类,主要负责处理与菜品(Dish)相关的各种业务逻辑操作,
|
|
|
|
|
|
|
|
* 它依赖于DishMapper(数据访问层接口,用于与数据库进行交互)来完成数据的持久化和查询等基础操作,通过调用DishMapper的对应方法以及运用一些业务规则处理,实现了诸如菜品的分页查询、新增、删除、修改、状态变更以及根据不同条件查询菜品等功能,
|
|
|
|
|
|
|
|
* 在整个系统架构中起到了承上启下的作用,将上层控制器层的请求转化为对数据库的具体操作,并按照业务需求处理返回结果,为菜品管理相关业务提供核心的逻辑支持。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Service
|
|
|
|
|
|
|
|
public class DishServiceImpl implements DishService {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 通过自动注入的方式获取DishMapper对象,DishMapper中定义了与菜品相关的各种数据库操作方法,
|
|
|
|
|
|
|
|
* 例如菜品数据的分页查询、单个菜品查询、菜品数据的新增、删除、更新以及与菜品口味等相关的数据操作方法,本业务逻辑实现类中的各个业务方法会调用其对应的方法来完成具体的数据库交互操作,实现菜品业务逻辑功能。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
|
|
|
DishMapper dishMapper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 菜品分页查询的业务方法,实现了DishService接口中定义的pageQuery方法,用于根据传入的分页查询条件对象(DishPageQueryDTO)进行菜品数据的分页查询操作,
|
|
|
|
|
|
|
|
* 首先从DishPageQueryDTO对象中获取页码(page)和每页显示记录数(pageSize)信息,然后借助PageHelper工具(用于在MyBatis中方便地实现分页功能)启动分页查询,
|
|
|
|
|
|
|
|
* 调用DishMapper的pageQuery方法获取分页查询结果(以Page<Dish>对象形式返回,其中包含了查询到的当前页菜品数据以及分页相关的统计信息,如总记录数等),
|
|
|
|
|
|
|
|
* 接着从Page<Dish>对象中提取出总记录数(total)和当前页的菜品数据列表(dishes),最后构建一个PageResult对象,将总记录数和菜品数据列表设置进去,返回该PageResult对象给上层调用者(通常是控制器层),
|
|
|
|
|
|
|
|
* 以便在前端页面进行分页展示菜品信息,满足用户分页查看菜品列表的需求。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param dishPageQueryDTO 包含分页查询条件的传输对象,其中有页码、每页记录数以及可能的筛选条件等信息,用于指定具体的菜品分页查询要求,获取相应的分页数据。
|
|
|
|
|
|
|
|
* @return 返回一个PageResult对象,用于封装分页查询结果,包含了总记录数(total)和当前页的菜品记录列表(records)等信息,方便上层进行分页数据的处理和展示。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
|
|
|
|
|
|
|
|
int page = dishPageQueryDTO.getPage();
|
|
|
|
|
|
|
|
int pageSize = dishPageQueryDTO.getPageSize();
|
|
|
|
|
|
|
|
// 开始分页查询,通过PageHelper设置当前页码和每页显示数量,后续执行的数据库查询会自动按照此分页设置进行操作
|
|
|
|
|
|
|
|
PageHelper.startPage(page, pageSize);
|
|
|
|
|
|
|
|
Page<Dish> pageResult = dishMapper.pageQuery(dishPageQueryDTO);
|
|
|
|
|
|
|
|
// 取出查询总数,即满足查询条件的所有记录数量,通过Page对象的getTotal方法获取
|
|
|
|
|
|
|
|
long total = pageResult.getTotal();
|
|
|
|
|
|
|
|
// 取出查询结果,即当前页的菜品数据列表,通过Page对象的getResult方法获取
|
|
|
|
|
|
|
|
List<Dish> dishes = pageResult.getResult();
|
|
|
|
|
|
|
|
// 构建查询结果对象,用于将分页相关的数据按照统一的格式返回给上层调用者
|
|
|
|
|
|
|
|
PageResult pageResult1 = new PageResult();
|
|
|
|
|
|
|
|
pageResult1.setTotal(total);
|
|
|
|
|
|
|
|
pageResult1.setRecords(dishes);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return pageResult1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 新增菜品和口味的业务方法,该方法使用了@Transactional注解,用于标记这个方法在执行过程中涉及的数据库操作应该在一个事务中进行,保证数据的一致性和完整性,
|
|
|
|
|
|
|
|
* 例如在新增菜品及其口味信息时,如果其中某个操作失败,整个操作都应该回滚,避免出现部分数据插入成功而部分失败导致的数据不一致情况。
|
|
|
|
|
|
|
|
* 首先将传入的DishDTO对象中的属性值复制到一个新创建的Dish实体对象中(通过BeanUtils.copyProperties方法实现属性值的拷贝),并设置菜品状态为启用状态(通过StatusConstant.ENABLE常量表示,假设这是定义好的表示启用的状态值),
|
|
|
|
|
|
|
|
* 然后调用DishMapper的save方法将菜品数据插入到菜品表中,获取插入后菜品的id(通常是数据库自动生成的主键值),接着获取DishDTO中包含的菜品口味列表(flavors),
|
|
|
|
|
|
|
|
* 如果口味列表不为空且包含元素,遍历口味列表,为每个口味对象设置对应的菜品id,最后调用DishMapper的insertBatchFlavors方法将这些口味数据批量插入到口味表中,实现菜品及其口味信息的同时新增操作,
|
|
|
|
|
|
|
|
* 常用于在管理员添加新菜品以及对应的口味时调用,完成菜品相关数据的完整添加过程。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param dishDTO 包含菜品及其口味详细信息的传输对象,例如菜品名称、价格、分类等菜品信息以及多个口味的具体描述(如口味名称、辣度等口味相关属性),用于在新增菜品时提供完整的数据支持。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Transactional
|
|
|
|
|
|
|
|
public void saveWithFlaver(DishDTO dishDTO) {
|
|
|
|
|
|
|
|
// 向菜品表添加一条数据,创建一个新的Dish实体对象,用于接收从DishDTO拷贝过来的属性值
|
|
|
|
|
|
|
|
Dish dish = new Dish();
|
|
|
|
|
|
|
|
BeanUtils.copyProperties(dishDTO, dish);
|
|
|
|
|
|
|
|
dish.setStatus(StatusConstant.ENABLE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dishMapper.save(dish);
|
|
|
|
|
|
|
|
// 向口味表添加n条数据,获取刚插入菜品的id,后续用于关联口味与菜品
|
|
|
|
|
|
|
|
Long dishId = dish.getId();
|
|
|
|
|
|
|
|
List<DishFlavor> flavors = dishDTO.getFlavors();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (flavors!= null && flavors.size() > 0) {
|
|
|
|
|
|
|
|
flavors.forEach(dishFlavor -> {
|
|
|
|
|
|
|
|
dishFlavor.setDishId(dishId);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
dishMapper.insertBatchFlavors(flavors);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 删除菜品的业务方法,用于批量删除菜品数据,但在删除之前需要进行一些业务规则的校验,
|
|
|
|
|
|
|
|
* 首先通过调用DishMapper的getByIdBatch方法获取要删除的菜品列表(根据传入的菜品id列表ids查询),然后遍历这些菜品,检查每个菜品的状态,
|
|
|
|
|
|
|
|
* 如果菜品处于起售状态(通过StatusConstant.ENABLE判断,起售期间按照业务规则通常不允许删除),则抛出DeletionNotAllowedException异常(自定义的异常类型,用于表示不允许删除的情况),并传递相应的提示信息(通过MessageConstant.DISH_ON_SALE常量表示,假设这是定义好的提示菜品正在销售不能删除的消息),
|
|
|
|
|
|
|
|
* 接着检查菜品是否被套餐绑定,通过调用DishMapper的countMealDish方法统计与传入的菜品id列表相关联的套餐菜品数量,如果数量大于0(表示有套餐绑定了这些菜品),同样抛出DeletionNotAllowedException异常,并传递相应的提示信息(通过MessageConstant.DISH_BE_RELATED_BY_SETMEAL常量表示,假设这是定义好的提示菜品被套餐关联不能删除的消息),
|
|
|
|
|
|
|
|
* 只有当菜品既不在起售状态且未被套餐绑定的情况下,才调用DishMapper的deleteBatch方法,根据传入的菜品id列表执行批量删除操作,实现菜品数据的批量删除功能,确保删除操作符合业务规则,避免误删正在使用的菜品数据。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param ids 包含要批量删除的菜品id的集合,通过该集合可以确定要从数据库中删除哪些菜品记录,但需要经过业务规则校验后才能执行实际的删除操作。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public void deleteBatch(ArrayList<Long> ids) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 判断菜品是否在起售,起售期间不能被删除,通过查询数据库获取对应菜品列表,遍历检查状态
|
|
|
|
|
|
|
|
ArrayList<Dish> dishs = dishMapper.getByIdBatch(ids);
|
|
|
|
|
|
|
|
for (Dish dish : dishs) {
|
|
|
|
|
|
|
|
if (dish.getStatus() == StatusConstant.ENABLE) {
|
|
|
|
|
|
|
|
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 判断菜品是否被套餐绑定,绑定期间不能被删除,通过查询统计与菜品关联的套餐菜品数量来判断
|
|
|
|
|
|
|
|
Integer count = dishMapper.countMealDish(ids);
|
|
|
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
|
|
|
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dishMapper.deleteBatch(ids);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 修改菜品的业务方法,该方法同样使用了@Transactional注解,保证修改菜品及其相关口味信息的操作在一个事务内执行,确保数据的一致性,
|
|
|
|
|
|
|
|
* 首先将传入的DishDTO对象中的属性值复制到一个新创建的Dish实体对象中(通过BeanUtils.copyProperties方法实现属性值的拷贝),然后获取DishDTO中的菜品口味列表(flavors),为每个口味对象设置对应的菜品id(即要修改的菜品的id),
|
|
|
|
|
|
|
|
* 接着调用DishMapper的updateDish方法更新菜品表中的菜品基本信息,之后先调用DishMapper的deleteBatchFlavors方法删除该菜品原有的口味数据(可能是因为口味有修改,先删除旧的口味记录),再调用insertBatchFlavors方法插入更新后的口味数据,实现菜品及其口味信息的完整修改操作,
|
|
|
|
|
|
|
|
* 常用于管理员修改菜品的相关属性(如名称、价格等)以及对应的口味信息时调用,保证菜品数据的准确性和完整性。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param dishDTO 包含修改后菜品及其口味详细信息的传输对象,例如修改后的菜品名称、价格、分类等菜品信息以及多个口味的具体描述(如口味名称、辣度等口味相关属性),用于更新数据库中对应菜品及其口味的记录。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Transactional
|
|
|
|
|
|
|
|
public void updateDish(DishDTO dishDTO) {
|
|
|
|
|
|
|
|
Dish dish = new Dish();
|
|
|
|
|
|
|
|
BeanUtils.copyProperties(dishDTO, dish);
|
|
|
|
|
|
|
|
List<DishFlavor> flavors = dishDTO.getFlavors();
|
|
|
|
|
|
|
|
flavors.forEach(dishFlavor -> {
|
|
|
|
|
|
|
|
dishFlavor.setDishId(dish.getId());
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新菜品,调用数据访问层方法更新菜品基本信息
|
|
|
|
|
|
|
|
dishMapper.updateDish(dish);
|
|
|
|
|
|
|
|
// 更新菜品对应的口味,先删除原有的口味数据,再插入更新后的口味数据
|
|
|
|
|
|
|
|
dishMapper.deleteBatchFlavors(flavors);
|
|
|
|
|
|
|
|
dishMapper.insertBatchFlavors(flavors);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据id获取菜品数据的业务方法,用于根据传入的菜品id查询对应的菜品详细信息以及其关联的口味信息,
|
|
|
|
|
|
|
|
* 首先创建一个包含传入id的ArrayList<Long>集合(方便后续调用以集合为参数的查询方法),然后通过调用DishMapper的getByIdBatch方法(假设该方法可以根据传入的id列表查询对应的菜品列表,这里只传入了一个id,所以只会获取到一个菜品对象)获取对应的菜品对象,
|
|
|
|
|
|
|
|
* 接着通过调用DishMapper的getFlavorById方法根据菜品id查询该菜品的口味列表,之后创建一个DishVO对象(假设这是用于展示菜品详细信息的视图对象,包含了菜品本身信息以及口味信息等),
|
|
|
|
|
|
|
|
* 通过BeanUtils.copyProperties方法将菜品对象的属性值复制到DishVO对象中,并将查询到的口味列表设置到DishVO对象的对应属性中,最后返回这个包含菜品详细信息和口味信息的DishVO对象给上层调用者,
|
|
|
|
|
|
|
|
* 方便在需要查看特定菜品详细情况(如在菜品详情页面展示)时获取完整的数据进行展示。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param id 要查询的菜品的唯一标识符,通过该id可以在数据库中精准定位到对应的菜品记录,获取其详细信息以及关联的口味信息。
|
|
|
|
|
|
|
|
* @return 返回一个DishVO对象,其中包含了查询到的菜品的详细信息(如菜品名称、价格、分类等)以及对应的口味信息(如口味名称、辣度等口味相关属性),便于展示菜品的完整详情。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public DishVO getById(Long id) {
|
|
|
|
|
|
|
|
ArrayList<Long> ids = new ArrayList<>();
|
|
|
|
|
|
|
|
ids.add(id);
|
|
|
|
|
|
|
|
// 根据id获取菜品,调用数据访问层方法获取对应菜品对象
|
|
|
|
|
|
|
|
Dish dish = dishMapper.getByIdBatch(ids).get(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 根据菜品id获取该菜品的口味,调用数据访问层方法获取菜品对应的口味列表
|
|
|
|
|
|
|
|
ArrayList<DishFlavor> dishFlavors = dishMapper.getFlavorById(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DishVO dishVO = new DishVO();
|
|
|
|
|
|
|
|
BeanUtils.copyProperties(dish, dishVO);
|
|
|
|
|
|
|
|
dishVO.setFlavors(dishFlavors);
|
|
|
|
|
|
|
|
return dishVO;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据分类id获取菜品的业务方法,直接调用DishMapper的getByCategoryId方法(假设该方法可以根据传入的分类id以及可能的其他筛选条件,这里第二个参数传入null表示无其他额外筛选条件)查询对应分类下的菜品列表,
|
|
|
|
|
|
|
|
* 并以ArrayList<Dish>集合形式返回查询结果,返回的菜品列表包含了属于该分类的所有菜品对象(每个菜品对象包含了菜品自身的详细信息,如菜品名称、价格、状态等),方便在需要按照分类查看菜品时获取相应的数据,
|
|
|
|
|
|
|
|
* 例如在前端展示菜品分类页面时,获取某个分类下的所有菜品进行展示。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param categoryId 菜品分类的唯一标识符,通过该id可以在数据库中查找属于该分类的所有菜品记录,获取相应的菜品列表。
|
|
|
|
|
|
|
|
* @return 返回一个ArrayList<Dish>对象,代表属于传入分类id的菜品列表,其中的泛型Dish表示每个元素是一个菜品实体对象,包含了菜品的各种属性信息(如菜品名称、价格、状态等)。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public ArrayList<Dish> getByCategoryId(Long categoryId) {
|
|
|
|
|
|
|
|
return dishMapper.getByCategoryId(categoryId, null);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 起售或停售菜品的业务方法,用于变更菜品的销售状态,首先创建一个Dish实体对象,将传入的菜品id(id)和要设置的状态值(status)设置到该对象的对应属性中,
|
|
|
|
|
|
|
|
* 然后调用DishMapper的updateDish方法,根据传入的包含菜品id和新状态的Dish对象,更新数据库中对应菜品记录的状态字段,实现菜品销售状态的变更操作,
|
|
|
|
|
|
|
|
* 常用于管理员在后台管理系统中对菜品进行起售(如将状态设置为启用状态)或停售(如将状态设置为禁用状态)的操作场景,方便控制菜品的售卖情况。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param id 要变更销售状态的菜品的唯一标识符,通过该id可以在数据库中精准定位到对应的菜品记录,进行状态修改操作。
|
|
|
|
|
|
|
|
* @param status 要设置的菜品销售状态值,例如1表示起售,0表示停售等,用于确定将菜品设置为哪种销售状态,改变数据库中对应菜品记录的状态字段内容。
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
public void startOrStop(Long id, Integer status) {
|
|
|
|
|
|
|
|
Dish dish = new Dish();
|
|
|
|
|
|
|
|
dish.setStatus(status);
|
|
|
|
|
|
|
|
dish.setId(id);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dishMapper.updateDish(dish);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 根据菜品分类和起售状态查询菜品的业务方法,首先根据传入的Dish实体对象中的分类id(通过dish.getCategoryId()获取)以及起售状态(通过dish.getStatus()获取)调用DishMapper的getByCategoryId方法查询对应的菜品列表(以ArrayList<Dish>集合形式返回),
|
|
|
|
|
|
|
|
* 接着遍历查询到的菜品列表,对于每个菜品,创建一个DishVO对象,通过BeanUtils.copyProperties方法将菜品对象的属性值复制到DishVO对象中,然后再根据菜品的id调用DishMapper的getFlavorById方法获取该菜品的口味列表,并设置到DishVO对象的对应属性中,
|
|
|
|
|
|
|
|
* 最后将构建好的包含菜品详细信息和口味信息的DishVO对象添加到一个新的ArrayList<DishVO>集合中,遍历完成后返回这个包含所有符合条件的菜品及其口味信息的DishVO对象列表,
|
|
|
|
|
|
|
|
* 方便在需要按照分类和销售状态展示菜品详情(包括口味信息)时获取相应的数据进行展示,例如在前端展示某个分类下正在销售的菜品及其口味列表的场景。
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @param dish 包含菜品分类id和起售状态等查询条件的菜品实体对象,通过其属性值可以确定要查询哪些菜品,例如指定分类以及
|