一、公共字段填充
1.1、问题分析
1.2、实现思路
1.3、代码开发
1.3.1、自定义注解
import com.sky.enumeration.OperationType;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target ( ElementType.METHOD )
@Retention ( RetentionPolicy.RUNTIME )
public @interface AutoFill {//通过枚举类型指定数据库操作的类型//UPDATE INSERTOperationType value();
}
1.3.2、切面类
import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.LocalDateTime;/*** 自定义切面,实现公共公共部分自动填充的逻辑*/
@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){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 setCreatTime = 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 );//通过反射进行赋值setCreatTime.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 ();}//为两个公共字段赋值}}}
二、新增菜品
2.1、需求分析和设计
2.2、文件上传
1.Controller层
import com.sky.result.Result;
import com.sky.utils.AliOssUtil;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.UUID;/*** 通用接口*/
@RestController
@RequestMapping("/admin/common")
@Slf4j
@Api(tags = "通用接口")
public class CommonController {@Autowiredprivate AliOssUtil aliOssUtil;/*** 文件上传* @param file* @return*/@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 (IOException e) {log.error ( "文件上传失败,{}",e );}return Result.error ( "文件上传失败" );}}
2.3、新增菜品
1.DishController
/*** 新增菜品* @param dishDTO* @return*/@PostMapping@ApiOperation ( "新增菜品" )public Result save(@RequestBody DishDTO dishDTO){log.info ( "新增菜品,{}",dishDTO );dishService.saveWithFlavor (dishDTO);return Result.success ();}
2.DishServiceImlp
/*** 新增菜品和对应的口味* @param dishDTO*/@Transactional //注解方式的事务管理 操作多张表保证数据的原子性,一致性@Overridepublic void saveWithFlavor(DishDTO dishDTO) {Dish dish = new Dish ();BeanUtils.copyProperties ( dishDTO,dish );//向菜品表插入一条数据dishMapper.insert(dish);//获取Insert语句生成的主键值Long dishId = dish.getId ();//向口味表插入n条数据List<DishFlavor> flavors = dishDTO.getFlavors ();if (flavors !=null && flavors.size () >0){flavors.forEach ( dishFlavor -> dishFlavor.setDishId ( dishId ));//向口味表插入n条数据dishFlavorMapper.insertBatch(flavors);}
3.Mapper
import com.sky.annotation.AutoFill;
import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.enumeration.OperationType;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface DishMapper {/*** 根据分类id查询菜品数量* @param categoryId* @return*/@Select("select count(id) from dish where category_id = #{categoryId}")Integer countByCategoryId(Long categoryId);/*** 修改菜品信息* @param dishDTO*/void updateDish(DishDTO dishDTO);/*** 新增菜品* @param dish*/@AutoFill ( OperationType.INSERT )void insert(Dish dish);
}
import com.sky.entity.DishFlavor;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* @param flavors*/void insertBatch(List<DishFlavor> flavors);
}
4.XML
<insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into dish(id,name,category_id,price,image,description,status,create_time,update_time,create_user,update_user)values(#{id},#{name},#{categoryId},#{price},#{image},#{description},#{status},#{createTime},#{updateTime},#{createUser},#{updateUser})</insert>
<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>
三、菜品分页查询
3.1、需求分析设计
3.2、代码实现
1.Controller
/*** 菜品分页查询* @param dishPageQueryDTO* @return*/@ApiOperation ( "菜品分页查询" )@GetMapping("/page")public Result<PageResult> dishPageQuery(DishPageQueryDTO dishPageQueryDTO){log.info ( "分页查询,{}",dishPageQueryDTO );PageResult pageResult= dishService.dishPageQuery(dishPageQueryDTO);return Result.success (pageResult);}
2.Service
/*** 菜品分页查询* @param dishPageQueryDTO* @return*/@ApiOperation ( "菜品分页查询" )@GetMapping("/page")public Result<PageResult> dishPageQuery(DishPageQueryDTO dishPageQueryDTO){log.info ( "分页查询,{}",dishPageQueryDTO );PageResult pageResult= dishService.dishPageQuery(dishPageQueryDTO);return Result.success (pageResult);}
3.Mapper
<!--分页查询--><select id="dishPageQuery" resultType="com.sky.vo.DishVO">select d.* ,c.name as categoryName from dish d left outer join category c on d.category_id = c.id<where><if test="name !=null"> and d.name like concat('%',#{name},'%')</if><if test="categoryId !=null">and d.category_id =#{categoryId}</if><if test="status !=null"> and d.status=#{status}</if></where>order by d.create_time desc</select>
四、删除菜品
4.1、需求分析与设计
4.2、代码实现
1.Controller层
/*** 批量删除菜品* @param ids* @return*/@DeleteMapping@ApiOperation ( "批量删除菜品" )public Result delete(@RequestParam List<Long> ids ){log.info ( "批量删除菜品,{}",ids );dishService.deleteBatch(ids);return Result.success ();}
2.Service层
/*** 批量删除* @param ids*/@Transactional@Overridepublic 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);}}
3.Mapper层
<?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"><!--根据菜品ID查询套餐ID--><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>
import com.sky.entity.DishFlavor;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface DishFlavorMapper {/*** 批量插入口味数据* @param flavors*/void insertBatch(List<DishFlavor> flavors);/*** 根据菜品id删除对应的口味数据* @param dishId*/@Delete ( "delete from dish_flavor where dish_id=#{dishId}" )void deleteByDishId(Long dishId);
}
五、修改菜品
5.1、需求分析设计
5.2、根据ID查询菜品接口开发
service层
/*** 根据ID查询菜品信息及口味* @param id* @return*/@Transactional@Overridepublic DishVO getById(Long id) {Dish dish =dishMapper.getById ( id );List<DishFlavor> flavors = dishFlavorMapper.getFlavor(id);DishVO dishVO = new DishVO ();BeanUtils.copyProperties ( dish,dishVO );dishVO.setFlavors ( flavors );return dishVO;}
5.3、修改菜品接口开发
1.Controller层
/*** 修改菜品信息* @param dishDTO* @return*/@PutMapping@ApiOperation ( "修改菜品" )public Result updateDish(@RequestBody DishDTO dishDTO){log.info ( "修改菜品,{}",dishDTO );dishService.updateDish(dishDTO);return Result.success ();}
2.Service层
/*** 修改菜品* @param dishDTO*/@AutoFill ( value = OperationType.UPDATE)@Overridepublic void updateDish(DishDTO dishDTO) {//修改菜品基本信息Dish dish = new Dish ();BeanUtils.copyProperties ( dishDTO,dish );dishMapper.updateDish(dish);//删除原有的口味数据dishFlavorMapper.deleteByDishId (dishDTO.getId () );//重新插入口味数据List<DishFlavor> flavors = dishDTO.getFlavors ();if (flavors !=null && flavors.size ()>0){flavors.forEach ( dishFlavor ->{dishFlavor.setDishId ( dishDTO.getId () );} );dishFlavorMapper.insertBatch ( flavors );}}
3.Mapper层
<update id="updateDish">update dish<set><if test="categoryId !=null">category_id=#{categoryId},</if><if test="description !=null">description=#{description},</if><if test="id !=null">id =#{id},</if><if test="image !=null">image =#{image},</if><if test="name !=null">name =#{name},</if><if test="price !=null">price =#{price},</if><if test="status !=null">status=#{status}</if></set>where id=#{id}</update>
<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>
/*** 根据菜品id删除对应的口味数据* @param dishId*/@Delete ( "delete from dish_flavor where dish_id=#{dishId}" )void deleteByDishId(Long dishId);