您的位置:首页 > 财经 > 金融 > 望野李梦阳_郑州市建设工程信息网官网_2022年适合小学生的新闻_关键字有哪些

望野李梦阳_郑州市建设工程信息网官网_2022年适合小学生的新闻_关键字有哪些

2024/12/22 1:15:52 来源:https://blog.csdn.net/LB_Wuyanzu/article/details/144197663  浏览:    关键词:望野李梦阳_郑州市建设工程信息网官网_2022年适合小学生的新闻_关键字有哪些
望野李梦阳_郑州市建设工程信息网官网_2022年适合小学生的新闻_关键字有哪些

外卖开发(三)开发笔记

  • 一、AOP实现实现公共字段填充(减少重复工作)
    • 实现思路
    • 自定义注解AutoFill
    • 自定义切面AutoFillAspect
    • 在Mapper接口上添加`@AutoFill`注解
  • 二、主键回显情况
  • 三、抛异常 和 事务管理

一、AOP实现实现公共字段填充(减少重复工作)

在这里插入图片描述

实现思路

在这里插入图片描述
1、自定义注解@AutoFill,用于表示需要进行公共字段填充的方法
2、自定义切面类,AutoFillAspect ,统一拦截加入了@AutoFill注解的方法,通过反射为公共字段赋值。
3、在Mapper方法上加入@AutoFill注解,因为这里我们的公共字段是更新时间、更新人、创建时间、创建人,所以只在insert、和update操作时才需要进行AutoFill。在进行Mapper方法前,先将实体类对象的相关属性填充,然后在进行insertupdate(before前置通知)

自定义注解AutoFill

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {/*** 定义注解的value值,对应数据操作类型insert 和 update* @return*/OperationType value();
}

自定义枚举

/*** 数据库操作类型*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}

自定义切面AutoFillAspect

/*** 自定义通知类,实现公共字段填充*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {@Pointcut("@annotation(com.sky.annotation.AutoFill)")public void pointCut(){}@Before("pointCut()")public void autoFill(JoinPoint joinPoint) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {log.info("开始进行字段填充");//获取当前被拦截方法的数据库操作类型MethodSignature signature = (MethodSignature) joinPoint.getSignature();AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);OperationType operationType = autoFill.value();//获取当前方法的参数--实体类对象   反射Object[] pointArgs = joinPoint.getArgs();if(pointArgs[0] == null){return;}Object entity = pointArgs[0];LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();//根据不同的操作类型,为对应的属性通过反射来赋值if(operationType == OperationType.INSERT){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);}else if(operationType == OperationType.UPDATE){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);}}
}

在Mapper接口上添加@AutoFill注解

在这里插入图片描述
此时,我们就不需要在service中重复进行字段的填充。

二、主键回显情况

如:新增菜品
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

涉及到了两张表,dish表和dish_flavor表。

dish表
在这里插入图片描述

dish_flavor表

在这里插入图片描述
DishDTO.java

public class DishDTO implements Serializable {private Long id;//菜品名称private String name;//菜品分类idprivate Long categoryId;//菜品价格private BigDecimal price;//图片private String image;//描述信息private String description;//0 停售 1 起售private Integer status;//口味private List<DishFlavor> flavors = new ArrayList<>();}

分析:新增dish操作,需要进行两次insert,分别插入dish表和dish_flavor表,但是我们从前端接收到的数据中(DishDTO)List<DishFlavor>中只包含了我们新增的口味名称口味值,并不会包含对应的dish_id,那么我们就需要把第一次向dish表中插入新数据时自动生成的id回显(带回来),并付给List<DishFlavor>中的dish_id。

DishService.java

/*** 新增菜品* @param dishDTO*/@Overridepublic void insertDish(DishDTO dishDTO) {Dish dish = new Dish();BeanUtils.copyProperties(dishDTO,dish);dishMapper.insert(dish);//获取inser之后的主键Long dishId = dish.getId();List<DishFlavor> flavors = dishDTO.getFlavors();if(flavors != null && flavors.size()>0){flavors.forEach(dishFlavor -> {dishFlavor.setDishId(dishId);  //将回显的主键id赋给flavir中的dish_id});dishFlavorMapper.insertBatch(flavors);}}
	/*** 批量新增dish* @param flavors*/@AutoFill(OperationType.INSERT)void insert(Dish dish);/*** 批量新增dish_flavor* @param flavors*/void insertBatch(List<DishFlavor> flavors);
<!--插入新菜品--><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>

三、抛异常 和 事务管理

在删除某个菜品的时候,如果这个菜品的状态为起售(status=1)时,就无法进行删除,需要停止删除操作,并抛出相关异常。如果这个菜品正在被一些套餐关联,那么也不能删除。

在删除菜品的时候,也要删除相关的菜品对应的口味,所以需要删除两个表。显而易见,我们需要进行事务管理

/*** 批量删除菜品* @param ids*/@Override@Transactional  //开启事务public void deleteDish(List<Long> ids) {//是否存在起售中的 存在就不能删除//利用count(1)计算出准备删除的菜品中status=1 的数量,如果大于0,说明存在起售中的Integer status = dishMapper.queryStatus(ids); if (status > 0){//抛出自定义的异常和异常信息:无法删除存在起售的菜品throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);}//查询有没有关联套餐 关联就不能删除//使用count(1)查询套餐中对应dish是否存在,如果大于0则不能删除Integer integer = setmealDishMapper.countDish(ids);if(integer > 0){//抛出自定义的异常和异常信息:无法删除存在关联的菜品throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);}//删除dish表中的数据dishMapper.deleteDish(ids);//删除dish-flavor表dishFlavorMapper.deleteByDishId(ids);}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com