蒼穹外賣學習筆記——第三天

zgg1h發表於2024-04-10

菜品管理

公共欄位自動填充

問題分析

  • 業務表中存在公共欄位:
欄位名 含義 資料型別
create_time 建立時間 datetime
create_user 建立人id bigint
update_time 修改時間 datetime
update_user 修改人id bigint
  • 這些公共欄位會在多處被執行相同的操作,導致程式碼冗餘、不便於後期維護。

實現思路

  1. 自定義註解 AutoFill,用於標識需要進行公共欄位自動填充的方法。
  2. 自定義切面類 AutoFillAspect,統一攔截加入了 AutoFill 註解的方法,透過反射為公共欄位賦值。
  3. 在 Mapper 的方法上加入 AutoFill 註解。
  • 技術點:列舉、註解、AOP、反射。

程式碼開發

自定義註解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查詢菜品介面開發

根據根據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>

功能測試

  • 可以透過介面文件進行測試,最後完成前後端聯調測試即可。

相關文章