一.新增菜品接口文档
首先我们来分析新增菜品接口文档。


POST请求,url为“/admin/dish”。前端发来的请求参数为JSON格式,要使用@RequestBody注解。使用DishDTO进行参数的接收。
DishDTO.class
package com.sky.dto;
import com.sky.entity.DishFlavor;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@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<>();
}
其中口味列表中存储的是口味数据,我们定义了DishFlavor.class来封装口味数据。
DishFlavor.class
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 菜品口味
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DishFlavor implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
//菜品id
private Long dishId;
//口味名称
private String name;
//口味数据list
private String value;
}
由于是新增操作,返回值不需要。
二.Controller层
package com.sky.controller.admin;
import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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")
@Api(tags = "菜品相关接口")
@Slf4j
public class DishController {
@Autowired
private DishService dishService;
/**
* 新增菜品
* @param dishDTO
* @return
*/
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO) { // 前端传递过来的Json格式的数据,要使用@RequestBody注解修饰变量来接收
log.info("新增菜品:{}",dishDTO);
dishService.saveWithFlavor(dishDTO);
return Result.success();
}
}
三.Service层
接口
package com.sky.service;
import com.sky.dto.DishDTO;
import org.springframework.stereotype.Service;
@Service
public interface DishService {
/**
* 新增菜品
* @param dishDTO
*/
void saveWithFlavor(DishDTO dishDTO);
}
实现类
package com.sky.service.impl;
import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.service.DishService;
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 java.util.List;
import java.util.function.Consumer;
@Service
public class DishServiceImpl implements DishService {
@Autowired
private DishMapper dishMapper;
@Autowired
private DishFlavorMapper dishFlavorMapper;
/**
* 新增菜品
* @param dishDTO
*/
@Transactional // 要对dish表和dish_flavor表同时进行操作,因此要使用事务,这两个操作要么同时成功,要么同时失败
@Override
public void saveWithFlavor(DishDTO dishDTO) {
// 我们要往dish表里写入数据,因此要创建一个Dish对象,将该Dish对象插入表中
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO,dish);
// 向dish表插入1条数据
dishMapper.insert(dish);
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && flavors.size() > 0) {
// 注意:我们在dish_flavor往里插入数据的时候,需要拿到当前dish的id,才能插入到dish_flavor中的dishId字段
Long dishId = dish.getId(); // 直接这样获取是获取不到的,因为默认情况下,执行基础的insert操作,是不会把主键值返回的。即使在数据库中已为其分配了主键id,但是直接get是无法拿到的,这时候就要使用主键返回功能 https://www.bilibili.com/video/BV1m84y1w7Tb?spm_id_from=333.788.videopod.episodes&vd_source=29b615752ffbc51f0ac76a344682247a&p=126
flavors.forEach(dishFlavor -> {
dishFlavor.setDishId(dishId); // lambda表达式,遍历flavor集合并为其中的dishId属性赋值
});
// 向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors); // 批量插入
}
}
}
由于我们要向dish表中插入数据,因此我们要定义一个Dish类型的对象,这样更加符合表中字段的属性。我们使用BaseUtils中的copyProperties方法将前端传入过来的封装在DishDTO对象中的属性赋值给Dish对象,然后我们调用mapper层中的insert方法将该dish对象插入到表中。
接着我们要对前端提交过来的封装在List集合中的口味值进行处理,将该口味值插入到dish_flavor表中。
首先我们判断前端提交的口味集合中是否有值。如果有值,那就进行批量插入。但是这里要注意,当我们进行插入操作时,DishFlavor对象中的dishId字段需要获得到当前菜品的Id值。但是我们默认情况下,执行基础的insert操作,是不会把主键值返回的。即使在数据库中已为其分配了主键id,但是直接get是无法拿到的,这时候就要使用主键返回功能 https://www.bilibili.com/video/BV1m84y1w7Tb?spm_id_from=333.788.videopod.episodes&vd_source=29b615752ffbc51f0ac76a344682247a&p=126。
四.Mapper
DishMapper.java
package com.sky.mapper;
import com.sky.annotation.AutoFill;
import com.sky.entity.Dish;
import com.sky.enumeration.OperationType;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface DishMapper {
/**
* 根据category_id查询菜品中的该分类数
* @param categoryId
* @return
*/
@Select("select count(*) from dish where category_id = #{categoryId}")
Integer countByCategoryId(Long categoryId);
/**
* 新增菜品
* @param dish
*/
@AutoFill(value = OperationType.INSERT)
void insert(Dish dish);
}
在新增菜品mapper接口中,我们使用@AutoFill注解完成字段自动填充。
DishFlavorMapper.java
package com.sky.mapper;
import com.sky.entity.DishFlavor;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DishFlavorMapper {
/**
* 新增口味
* @param dishFlavors
*/
public void insertBatch(List<DishFlavor> dishFlavors); // 要进行批量添加,将集合中的元素都添加进去,因此要使用<foreach>
}
在新增口味字段中我们接收口味列表并进行批量添加。
DishMapper.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.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>
我们要使用主键返回功能,使得flavor拿到dishId,因此我们定义useGeneratedKeys="true",keyProperty="id"。即开启主键返回功能,并将dish表中的id字段返回。这样Long dishId = dish.getId();就可以拿到该id。
DishFlavorMapper.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.DishFlavorMapper">
<insert id="insertBatch">
insert into dish_flavor(dish_id, name, value) VALUES
<foreach collection="dishFlavors" item="dishFlavor" separator=",">
(#{dishFlavor.dishId}, #{dishFlavor.name}, #{dishFlavor.value})
</foreach>
</insert>
</mapper>
使用<foreach>批量添加flavor数据dish_flavor到表中。
