菜品管理
公共字段自动填充
问题分析
字段名 |
含义 |
数据类型 |
create_time |
创建时间 |
datetime |
create_user |
创建人id |
bigint |
update_time |
修改时间 |
datetime |
update_user |
修改人id |
bigint |
- 这些公共字段会在多处被执行相同的操作,导致代码冗余、不便于后期维护。
实现思路
- 自定义注解 AutoFill,用于标识需要进行公共字段自动填充的方法。
- 自定义切面类 AutoFillAspect,统一拦截加入了 AutoFill 注解的方法,通过反射为公共字段赋值。
- 在 Mapper 的方法上加入 AutoFill 注解。
代码开发
自定义注解AutoFill
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
//数据库操作类型:UPDATE INSERT
OperationType value();
}
自定义切面AutoFillAspect
@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) {
//待完善
}
}
完善自定义切面AutoFillAspect的autoFill方法
@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 setCreateTime = 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);
//通过反射为对象赋值
setCreateTime.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();
}
}
}
在Mapper接口的方法上加入AutoFill注解
//EmployeeMapper.java
@Insert("insert into employee (name, username, password, phone, sex, id_number, status, create_time, " +
"update_time, create_user, update_user) VALUES (#{name}, #{username}, #{password}, #{phone}, " +
"#{sex}, #{idNumber}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
@AutoFill(OperationType.INSERT)
void insert(Employee employee);
@AutoFill(OperationType.UPDATE)
void update(Employee employee);
//CategoryMapper.java
@Insert("insert into category(type, name, sort, status, create_time, update_time, create_user, " +
"update_user) VALUES (#{type}, #{name}, #{sort}, #{status}, #{createTime}, #{updateTime}, " +
"#{createUser}, #{updateUser})")
@AutoFill(OperationType.INSERT)
void insert(Category category);
@AutoFill(OperationType.UPDATE)
void update(Category category);
将业务层为公共字段赋值的代码注释掉
功能测试
- 通过观察控制台输出的SQL来确定公共字段填充是否完成。
新增菜品
需求分析和设计
产品原型
业务规则
- 菜品名称必须是唯一的。
- 菜品必须属于某个分类下,不能单独存在。
- 新增菜品时可以根据情况选择菜品的口味
- 每个菜品必须对应一张图片。
接口设计
根据类型查询分类(已完成)
文件上传
新增菜品
数据库设计
dish菜品表
字段名 |
数据类型 |
说明 |
备注 |
id |
bigint |
主键 |
自增 |
name |
varchar(32) |
菜品名称 |
唯一 |
category_id |
bigint |
分类id |
逻辑外键 |
price |
decimal(10,2) |
菜品价格 |
|
image |
varchar(255) |
图片路径 |
|
description |
varchar(255) |
菜品描述 |
|
status |
int |
售卖状态 |
1起售 0停售 |
create_time |
datetime |
创建时间 |
|
update_time |
datetime |
最后修改时间 |
|
create_user |
bigint |
创建人id |
|
update_user |
bigint |
最后修改人id |
|
dish_flavor口味表
字段名 |
数据类型 |
说明 |
备注 |
id |
bigint |
主键 |
自增 |
dish_id |
bigint |
菜品id |
逻辑外键 |
name |
varchar(32) |
口味名称 |
|
value |
varchar(255) |
口味值 |
|
代码开发
文件上传接口
在application-dev.yml配置阿里云相关信息
sky:
alioss:
endpoint: oss-cn-beijing.aliyuncs.com
access-key-id: LTAI5tPeFLzsPPT8gG3LPW64
access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7
bucket-name: sky-itcast
在application.yml引用application-dev.yml里的配置信息
sky:
alioss:
endpoint: ${sky.alioss.endpoint}
access-key-id: ${sky.alioss.access-key-id}
access-key-secret: ${sky.alioss.access-key-secret}
bucket-name: ${sky.alioss.bucket-name}
自定义配置类OssConfiguration为阿里云工具类AliOssUtil注入配置信息
@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());
}
}
自定义CommonController类并实现upload方法
@RestController
@RequestMapping("/admin/commom")
@Slf4j
@Api(tags = "通用接口")
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 extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//构造新文件名称
String objectName = UUID.randomUUID().toString() + extension;
//文件的请求路径
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);
} catch (Exception e) {
log.error("文件上传失败:{}", e);
}
return Result.error(MessageConstant.UPLOAD_FAILED);
}
}
新增菜品接口
根据新增菜品接口设计对应的DTO
@Data
public class DishDTO implements Serializable {
private Long id;
//菜品名称
private String name;
//菜品分类id
private Long categoryId;
//菜品价格
private BigDecimal price;
//图片
private String image;
//描述信息
private String description;
//0 停售 1 起售
private Integer status;
//口味
private List<DishFlavor> flavors = new ArrayList<>();
}
自定义DishController类并创建save方法
@RestController
@RequestMapping("/admin/dish")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {
@Autowired
private DishService dishService;
/**
* 新增菜品
*
* @param dishDTO
* @return
*/
@PostMapping
public Result save(@RequestBody DishDTO dishDTO) {
log.info("新增菜品:{}", dishDTO);
dishService.saveWithFlavor(dishDTO);
return Result.success();
}
}
自定义DishService接口并声明saveWithFlavor方法
public interface DishService {
/**
* 新增菜品和对应的口味数据
*
* @param dishDTO
*/
void saveWithFlavor(DishDTO dishDTO);
}
自定义DishServiceImpl实现类并实现saveWithFlavor方法
@Service
public class DishServiceImpl implements DishService {
@Autowired
private DishMapper dishMapper;
@Autowired
private DishFlavorMapper dishFlavorMapper;
/**
* 新增菜品和对应的口味数据
*
* @param dishDTO
*/
@Override
@Transactional
public void saveWithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO, dish);
//向菜品表插入1条数据
dishMapper.insert(dish);
//获取insert语句生成的主键值
Long dishId = dish.getId();
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && !flavors.isEmpty()) {
flavors = flavors.stream().filter(dishFlavor -> !Objects.equals(dishFlavor.getName(), "")).collect(Collectors.toList());
flavors.forEach(dishFlavor -> dishFlavor.setDishId(dishId));
//向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
}
在DishMapper中声明insert方法
@AutoFill(value = OperationType.INSERT)
void insert(Dish dish);
自定义DishMapper.xml并编写SQL
<?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="insert" useGeneratedKeys="true" keyProperty="id">
insert into dish (name, category_id, price, image, description, status, create_time, update_time, create_user, update_user)
values
(#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})
</insert>
</mapper>
自定义DishFlavorMapper接口并声明insertBatch方法
@Mapper
public interface DishFlavorMapper {
/**
* 批量插入口味数据
*
* @param flavors
*/
void insertBatch(List<DishFlavor> flavors);
}
自定义DishFlavorMapper.xml并编写SQL
<?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="insertBatch">
insert into dish_flavor (dish_id, name, value) VALUES
<foreach collection="flavors" item="df" separator=",">
(#{df.dishId}, #{df.name}, #{df.value})
</foreach>
</insert>
</mapper>
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。
菜品分页查询
需求分析和设计
产品原型
业务规则
- 根据页码展示菜品信息。
- 每页展示10条数据。
- 分页查询时可以根据需要输入菜品名称、菜品分类、菜品状态进行查询。
接口设计
代码开发
根据菜品分页查询接口定义设计对应的DTO
@Data
public class DishPageQueryDTO implements Serializable {
private int page;
private int pageSize;
private String name;
//分类id
private Integer categoryId;
//状态 0表示禁用 1表示启用
private Integer status;
}
根据菜品分页查询接口定义设计对应的VO
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DishVO implements Serializable {
private Long id;
//菜品名称
private String name;
//菜品分类id
private Long categoryId;
//菜品价格
private BigDecimal price;
//图片
private String image;
//描述信息
private String description;
//0 停售 1 起售
private Integer status;
//更新时间
private LocalDateTime updateTime;
//分类名称
private String categoryName;
//菜品关联的口味
private List<DishFlavor> flavors = new ArrayList<>();
}
根据接口定义创建DishController的page分页查询方法
@GetMapping("/page")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {
log.info("菜品分页查询:{}", dishPageQueryDTO);
PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}
在 DishService 中扩展分页查询方法
PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);
在 DishServiceImpl 中实现分页查询方法
@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());
}
在 DishMapper 接口中声明 pageQuery 方法
Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);
在 DishMapper.xml 中编写SQL
<select id="pageQuery" resultType="com.sky.vo.DishVO">
select d.*, c.name category_name from dish d left join category c on d.category_id = c.id
<where>
<if test="name != null">and d.name = #{name}</if>
<if test="name != null">and d.category_id = #{categoryId}</if>
<if test="name != null">and d.status = #{status}</if>
</where>
order by d.create_time desc
</select>
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。
删除菜品
需求分析和设计
产品原型
业务规则
- 可以一次删除一个菜品,也可以批量删除菜品。
- 启售中的菜品不能删除。
- 被套餐关联的菜品不能删除。
- 删除菜品后,关联的口味数据也需要删除掉。
接口设计
数据库设计
代码开发
根据删除菜品的接口定义在DishController中创建方法
@DeleteMapping
@ApiOperation("批量删除菜品")
public Result delete(@RequestParam List<Long> ids) {
log.info("批量删除菜品:{}", ids);
dishService.deleteBatch(ids);
return Result.success();
}
在DishService接口中声明deleteBatch方法
void deleteBatch(List<Long> ids);
在DishServiceImpl中实现deleteBatch方法
@Override
@Transactional
public void deleteBatch(List<Long> ids) {
for (Long id : ids) {
Dish dish = dishMapper.getById(id);
if (dish.getStatus().equals(StatusConstant.ENABLE)) {
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
}
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
if (setmealIds != null && !setmealIds.isEmpty()) {
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}
for (Long id : ids) {
dishMapper.deleteById(id);
dishFlavorMapper.deleteByDishId(id);
}
}
在DishMapper中声明getById方法,并配置SQL
@Select("select * from dish where id = #{id}")
Dish getById(Long id);
创建SetmealDishMapper,声明getSetmealIdsByDishIds方法,并在xml文件中编写SQL
//SetmealDishMapper.java
package com.sky.mapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SetmealDishMapper {
/**
* 根据菜品id查询对应的套餐id
*
* @param dishIds
* @return
*/
List<Long> getSetmealIdsByDishIds(List<Long> dishIds);
}
<!--SetmealDishMapper.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.SetmealDishMapper">
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
select setmeal_id from setmeal_dish where dish_id in
<foreach collection="dishIds" item="dishId" open="(" separator="," close=")">
#{dishId}
</foreach>
</select>
</mapper>
在DishMapper中声明deleteById方法并配置SQL
@Delete("delete from dish where id = #{id}")
void deleteById(Long id);
在DishFlavorMapper中声明deleteByDishId方法并配置SQL
@Delete("delete from dish_flavor where dish_id = #{dishId}")
void deleteByDishId(Long dishId);
代码优化:根据菜品id集合批量删除菜品数据及其关联的口味数据
//DishServiceImpl.java
@Override
@Transactional
public void deleteBatch(List<Long> ids) {
for (Long id : ids) {
Dish dish = dishMapper.getById(id);
if (dish.getStatus().equals(StatusConstant.ENABLE)) {
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
}
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
if (setmealIds != null && !setmealIds.isEmpty()) {
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}
dishMapper.deleteByIds(ids);
dishFlavorMapper.deleteByDishIds(ids);
}
//DishMapper.java
void deleteByIds(List<Long> ids);
//DishFlavorMapper.java
void deleteByDishIds(List<Long> dishIds);
<!--DishMapper.xml-->
<delete id="deleteByIds">
delete from dish where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<!--DishFlavorMapper.xml-->
<delete id="deleteByDishIds">
delete from dish_flavor where dish_id in
<foreach collection="dishIds" item="dishId" open="(" separator="," close=")">
#{dishId}
</foreach>
</delete>
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。
修改菜品
需求分析和设计
产品原型
接口设计
根据id查询菜品
根据类型查询分类(已实现)
文件上传(已实现)
修改菜品
代码开发
根据id查询菜品接口开发
根据根据id查询菜品的接口定义在DishController中创建方法
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品")
public Result<DishVO> getById(@PathVariable Long id) {
log.info("根据id查询菜品:{}", id);
DishVO dishVO = dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}
在DishService接口中声明getByIdWithFlavor方法
DishVO getByIdWithFlavor(Long id);
在DishServiceImpl中实现getByIdWithFlavor方法
@Override
@Transactional
public DishVO getByIdWithFlavor(Long id) {
Dish dish = dishMapper.getById(id);
List<DishFlavor> flavors = dishFlavorMapper.getByDishId(id);
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(dish, dishVO);
dishVO.setFlavors(flavors);
return dishVO;
}
在DishFlavorMapper中声明getByDishId方法,并配置SQL
@Select("select * from dish_flavor where dish_id = #{dishId}")
List<DishFlavor> getByDishId(Long dishId);
修改菜品接口开发
根据修改菜品的接口定义在DishController中创建方法
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO) {
log.info("修改菜品:{}", dishDTO);
dishService.updateWithFlavor(dishDTO);
return Result.success();
}
在DishService接口中声明updateWithFlavor方法
void updateWithFlavor(DishDTO dishDTO);
在DishServiceImpl中实现updateWithFlavor方法
@Override
@Transactional
public void updateWithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO, dish);
dishMapper.update(dish);
//先删除原来的口味数据
dishFlavorMapper.deleteByDishId(dishDTO.getId());
//再插入新的口味数据
Long dishId = dish.getId();
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && !flavors.isEmpty()) {
flavors = flavors.stream().filter(dishFlavor -> !dishFlavor.getName().isEmpty()).collect(Collectors.toList());
flavors.forEach(dishFlavor -> dishFlavor.setDishId(dishId));
//向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
在DishMapper中声明update方法
@AutoFill(OperationType.UPDATE)
void update(Dish dish);
在DishMapper.xml中声明update方法并配置SQL
<update id="update">
update dish
<set>
<if test="name != null">name = #{name},</if>
<if test="categoryId != null">category_id = #{categoryId},</if>
<if test="price != null">price = #{price},</if>
<if test="image != null">image = #{image},</if>
<if test="description != null">description = #{description},</if>
<if test="status != null">status = #{status},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUser != null">update_user = #{updateUser},</if>
</set>
where id = #{id}
</update>
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。
菜品启售停售
需求分析和设计
产品原型
业务规则
接口设计
代码开发
根据菜品启售停售的接口定义在DishController中创建方法
@PostMapping("/status/{status}")
@ApiOperation("菜品启售停售")
public Result startOrStop(@PathVariable Integer status, Long id) {
log.info("菜品启售停售:{},{}", status, id);
dishService.startOrStop(status, id);
return Result.success();
}
在DishService接口中声明startOrStop方法
void startOrStop(Integer status, Long id);
在DishServiceImpl中实现startOrStop方法
@Override
@Transactional
public void startOrStop(Integer status, Long id) {
Dish dish = Dish.builder()
.status(status)
.id(id)
.build();
dishMapper.update(dish);
if (status.equals(StatusConstant.DISABLE)) {
List<Long> dishIds = new ArrayList<>();
dishIds.add(id);
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
if (setmealIds != null && !setmealIds.isEmpty()) {
for (Long setmealId : setmealIds) {
Setmeal setmeal = Setmeal.builder()
.status(StatusConstant.DISABLE)
.id(setmealId)
.build();
setmealMapper.update(setmeal);
}
}
}
}
在SetmealMapper中声明update方法
@AutoFill(OperationType.UPDATE)
void update(Setmeal setmeal);
创建SetmealMapper.xml并编写SQL
<?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">
<update id="update">
update setmeal
<set>
<if test="categoryId != null">category_id = #{categoryId},</if>
<if test="name != null">name = #{name},</if>
<if test="price != null">price = #{price},</if>
<if test="status != null">status = #{status},</if>
<if test="description != null">description = #{description},</if>
<if test="image != null">image = #{image},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUser != null">update_user = #{updateUser},</if>
</set>
where id = #{id}
</update>
</mapper>
代码优化:根据套餐id集合批量修改套餐数据
//DishServiceImpl.java
@Override
@Transactional
public void startOrStop(Integer status, Long id) {
Dish dish = Dish.builder()
.status(status)
.id(id)
.build();
dishMapper.update(dish);
if (status.equals(StatusConstant.DISABLE)) {
List<Long> dishIds = new ArrayList<>();
dishIds.add(id);
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
if (setmealIds != null && !setmealIds.isEmpty()) {
setmealMapper.startOrStopBatch(setmealIds, StatusConstant.DISABLE);
}
}
}
//setmealMapper.java
@AutoFill(OperationType.UPDATE)
void startOrStopBatch(List<Long> setmealIds, Integer startOrStop);
//SetmealMapper.xml
<update id="startOrStopBatch">
update setmeal set status = #{startOrStop} where id in
<foreach collection="setmealIds" item="setmealId" open="(" separator="," close=")">
#{setmealId}
</foreach>
</update>
功能测试
- 可以通过接口文档进行测试,最后完成前后端联调测试即可。