赞
踩
场景:当添加一个菜品时,还需要记录菜品的口味信息,因此需要对菜品表(dish)和口味表(dish_flavor)同时进行插入操作。
两个表的字段:
代码思路:由DishController将前端的请求派发给相应的业务层(DishService),业务层随后通过调用持久层(DishMapper,DishFlavorMapper)进行数据的增删改。
细节:
代码(由上至下):
控制层:
DishController
package com.sky.controller.admin; import com.sky.dto.DishDTO; import com.sky.result.Result; import com.sky.service.DishService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * ClassName: DishController * PackageName: com.sky.controller.admin * Description: 菜品管理 * * @Author Xiyan Zhong * @Create 2023/12/20 下午2:19 * @Version 1.0 */ @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){ log.info("新增菜品:{}",dishDTO); dishService.saveWithFlavor(dishDTO); return Result.success(); } }
业务层:
DishService:
package com.sky.service; import com.sky.dto.DishDTO; /** * ClassName: DishService * PackageName: com.sky.service * Description: * * @Author Xiyan Zhong * @Create 2023/12/20 下午2:23 * @Version 1.0 */ public interface DishService { /** * 新增菜品和对应的口味 * @param dishDTO */ public void saveWithFlavor(DishDTO dishDTO); }
DishServiceImpl:
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 lombok.extern.slf4j.Slf4j; 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; /** * ClassName: DishServiceImpl * PackageName: com.sky.service.impl * Description: * * @Author Xiyan Zhong * @Create 2023/12/20 下午2:25 * @Version 1.0 */ @Service @Slf4j public class DishServiceImpl implements DishService { @Autowired private DishMapper dishMapper; @Autowired private DishFlavorMapper dishFlavorMapper; /** * 新增菜品和对应的口味 * @param dishDTO */ @Transactional // 操作多张表的时候,添加@Transactional注解,保证该事件是原子性的,要么全成功,要么全失败 @Override 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.size() > 0){ //遍历flavors,为每个口味附上相关的dishId flavors.forEach(dishFlavor -> { dishFlavor.setDishId(dishId); }); // 向口味表插入n条数据 dishFlavorMapper.insertBatch(flavors); } } }
需要注意的是,为了保证@Transactional有效,需要在当前项目的入口类添加@EnableTransactionManagement,启动注解方式的事务管理,如:
package com.sky; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication @EnableTransactionManagement //开启注解方式的事务管理 @Slf4j public class SkyApplication { public static void main(String[] args) { SpringApplication.run(SkyApplication.class, args); log.info("server started"); } }
持久层:
DishMapper 接口
package com.sky.mapper; import com.sky.annotation.AutoFill; import com.sky.entity.Dish; import com.sky.enumeration.OperationType; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; /** * ClassName: DishMapper * PackageName: com.sky.mapper * Description: * * @Author Xiyan Zhong * @Create 2023/12/15 下午2:52 * @Version 1.0 */ @Mapper public interface DishMapper { /** * 根据分类id查询菜品数量 * @param categoryId * @return */ @Select("select count(id) from dish where category_id = ${categoryId}") Integer countByCategoryId(Long categoryId); /** * 插入菜品数据 * @param dish */ @AutoFill(value = OperationType.INSERT) void insert(Dish dish); }
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">
<!--设置useGeneratedKeys="true" 表示需要获得插入数据后生成的主键值,返回到keyProperty="id",即Dish对象中的id属性-->
<insert id="insert" parameterType="Dish" useGeneratedKeys="true" keyProperty="id">
insert into dish (name, category_id, price, image, description, create_time, update_time, create_user, update_user, status)
values
(#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser},
#{status})
</insert>
</mapper>
DishFlavorMapper 接口
package com.sky.mapper; import com.sky.entity.DishFlavor; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * ClassName: DishFlavorMapper * PackageName: com.sky.mapper * Description: * * @Author Xiyan Zhong * @Create 2023/12/20 下午2:42 * @Version 1.0 */ @Mapper public interface DishFlavorMapper { /** * 批量插入口味数据 * @param flavors */ void insertBatch(List<DishFlavor> flavors); }
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" parameterType="DishFlavor">
insert into dish_flavor (dish_id, name, value)
values
<foreach collection="flavors" item="df" separator=",">
(#{df.dishId},#{df.name},#{df.value})
</foreach>
</insert>
</mapper>
场景:当删除一个菜品时,不仅要删除菜品表中的数据,同时也要删除口味表中对应数据和菜品与分类表中的数据。
相关表的关系:
代码思路:由DishController将前端的请求派发给相应的业务层(DishService),业务层随后通过调用持久层(DishMapper,DishFlavorMapper,SetmealDishMapper)进行数据的增删改。
细节:
代码(由上至下):
DishController
@DeleteMapping
@ApiOperation("菜品删除")
// 通过@RequestParam解析前端请求地址中字符串参数ids=1,2,3...为一个列表
public Result delete(@RequestParam List<Long> ids){
log.info("菜品批量删除:{}",ids);
dishService.deleteBatch(ids);
return Result.success();
}
DishService
/**
* 菜品的批量删除
* @param ids
*/
void deleteBatch(List<Long> ids);
DishServiceImpl
/** * 菜品的批量删除 * * @param ids */ @Transactional // 保证事务的原子性 @Override public void deleteBatch(List<Long> ids) { // 判断当前菜品是否能够删除——是否存在起售中 for (Long id : ids) { Dish dish = dishMapper.getById(id); if (dish.getStatus() == StatusConstant.ENABLE) { throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE); } } // 判断当前菜品是否能够删除——是否被套餐关联 List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids); if (setmealIds != null && setmealIds.size() > 0) { // 当前菜品被套餐关联了,不能删除 throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL); } // 删除菜品表中的菜品数据 /*for (Long id : ids) { dishMapper.deleteById(id); // 删除菜品关联的口味数据 dishFlavorMapper.deleteByDishId(id); }*/ // sql: delete from dish where id in (?,?,?) // 根据菜品id集合批量删除菜品数据 dishMapper.deleteByIds(ids); // 根据菜品id集合批量删除口味数据 dishFlavorMapper.deleteByDishIds(ids); }
SetmealDishMapper提供查询操作
SetmealDishMapper
package com.sky.mapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * ClassName: SetmealDishMapper * PackageName: com.sky.mapper * Description: * * @Author Xiyan Zhong * @Create 2023/12/20 下午7:29 * @Version 1.0 */ @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">
<!--对应sql语句:select setmeal_id from setmeal_dish where dish_id in (?,?,?)-->
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
select setmeal_id from setmeal_dish where dish_id in
<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
#{dishId}
</foreach>
</select>
</mapper>
其中分别实现了单个、批量删除操作
DishMapper
/**
* 根据主键删除菜品数据
* @param id
*/
@Delete("delete from dish where id = #{id}")
void deleteById(Long id);
/**
* 根据菜品id集合批量删除菜品
* @param ids
*/
void deleteByIds(List<Long> ids);
DishMapper.xml
<delete id="deleteByIds">
delete from dish where id in
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</delete>
DishFlavorMapper
/**
* 根据菜品id删除对应的口味数据
* @param dishId
*/
@Delete("delete from dish_flavor where dish_id = #{dishId}")
void deleteByDishId(Long dishId);
/**
* 据菜品id批量删除对应的口味数据
* @param dishIds
*/
void deleteByDishIds(List<Long> dishIds);
DishFlavorMapper.xml
<delete id="deleteByDishIds">
delete from dish_flavor where dish_id in
<foreach collection="dishIds" open="(" close=")" separator="," item="dishId">
#{dishId}
</foreach>
</delete>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。