这些字段在每张表基本都有,手动进行填充效率低,且后期维护更改繁琐
使用到注解+AOP主要
先答应一个AutoFill注解
package com.sky.aspect;
/**
* 自定义切面类,实现公共字段自动填充
*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
/**
* 切入点
*/
//不仅需要符合切入点表达式,且要满足方法上有对应注解
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void auotFillPointCut(){}
/**
* 前置通知,在通知中进行公共字段赋值
*/
@Before("auotFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始进行公共字段的自动填充...");
//获取方法上的数据库操作类型(决定是否需修改CreateUser和CreateTime)
MethodSignature signature = (MethodSignature) joinPoint.getSignature();//方法签名对象
AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);//获得方法上的注解对象
OperationType value = annotation.value();//获取数据库的操作类型
//获取方法上的参数--实体参数
Object[] args = joinPoint.getArgs();
if (args==null || args.length==0){
return;
}
Object entity=args[0];//可能接收不同实体,因为是公共字段,可能员工,菜品什么的都有,所以用object
//准备赋值数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();
//根据当前不同的操作类型,为对应属性进行赋值
if(value==OperationType.INSERT)
{
try {
//通过反射获取对应的方法
Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
//再进行赋值
setCreateTime.invoke(entity,now);
setUpdateTime.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateUser.invoke(entity,currentId);
} catch (Exception e) {
e.printStackTrace();
}
}
else if(value==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注解
所以我们在对应mapper文件的insert和update操作做上加上@AutoFill注解并且指定value(操作类型)
然后我们就可以把之前service中设置UpdateTime和UpdateUser以及Create的全都可以注释/删除
进行测试
我这里测试过了
提交推送即可
涉及到我们的菜品分类的回查
还有文件上传图片可以用阿里云的oss实现
先开发一个阿里云的服务
先写配置文件,来写我们的域名,bucket名,秘钥id和密码
第三方bean,写个配置类
配置上对应的参数
再写Commoncontroller
@RestController
@RequestMapping("/admin/common")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {
@Autowired
private AliOssUtil aliOssUtil;
@ApiOperation("文件上传")
@PostMapping("/upload")
public Result<String> upload(MultipartFile file){
log.info("文件上传:{}",file);
try {
//获取原始文件名
String originalFilename = file.getOriginalFilename();
//截取原始文件名后缀 xxx.jpg
String substring = originalFilename.substring(originalFilename.lastIndexOf('.'));
String uuid = UUID.randomUUID().toString();
//构造新文件名
String name=uuid+substring;
String filePath = aliOssUtil.upload(file.getBytes(), name);//返回值为文件请求路径
return Result.success(filePath);
} catch (IOException e) {
log.error("文件上传失败:{}",e);
}
return Result.error(MessageConstant.UPLOAD_FAILED);
}
}
这样就可以了,完成文件上传操作,用到了阿里云oss,不知道怎么用可以看一下我之前的文件上传博客
把对应权限改为公开权限就可以在别的地方看到对应图片
controller
@RestController
@RequestMapping("/admin/dish")
@Slf4j
@Api(tags = "菜品相关接口")
public class DishController {
@Autowired
private DishService dishService;
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}",dishDTO);
dishService.savewithFlavor(dishDTO);
return Result.success();
}
}
@Service
@Slf4j
public class DishServiceImpl implements DishService {
@Autowired
private DishMapper dishMapper;
@Autowired
private DishFlavorMapper dishFlavorMapper;
/**
* 新增菜品和对应的口味数据
* @param dishDTO
*/
@Transactional//事务注解,因为有两次操作的,一次修改菜品表,一次是口味表
public void savewithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO,dish);
//向菜品表插入1条数据
dishMapper.insert(dish);
//获取insert语句生产的主键值
Long id = dish.getId();
//向口味表插入n条数据
List<DishFlavor> flavors = dishDTO.getFlavors();
if(flavors != null && flavors.size() > 0) {
for (DishFlavor flavor:flavors
) {
flavor.setDishId(id);
}
dishFlavorMapper.insertBatch(flavors);
}
}
}
解释一下,分开两个表插入的其实是,所以我们要加上@Transactional的注解,进行一个事务操作,还要创建两个mapper
DishMapper
@Mapper
public interface DishMapper {
/**
* 根据分类id查询菜品数量
* @param categoryId
* @return
*/
@Select("select count(id) from dish where category_id = #{categoryId}")
Integer countByCategoryId(Long categoryId);
@AutoFill(value = OperationType.INSERT)
void insert(Dish dish);
}
对应xml
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,create_time,update_time,create_user,update_user,status)
values
(#{name},#{categoryId},#{price},#{image},#{description},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})
insert>
mapper>
DishFlavorMapper
@Mapper
public interface DishFlavorMapper {
/**
* 批量插入口味数据
* @param flavors
*/
@AutoFill(value = OperationType.INSERT)
void insertBatch(List<DishFlavor> flavors);
}
对应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="flavors" item="df" separator=",">
(#{df.dishId},#{df.name},#{df.value})
</foreach>
</insert>
</mapper>
然后就是前后端联调
我联调成功了
记得在insert操作上加@AutoFill不然不会自动加入创建人那些公共字段
controller
service
mapper+xml
测试成功
主要看能不能显示出菜品名称
dish表里无菜品分类名称这一个字段的,需要返回DishVO对象
但有category_id这个字段,可以在category里面查到
需要从category里查
这里设计到多表查询了,而且是以一个表的字段匹配另一个表
这里直接用了左外连接进行查询
注意点
两点
1.在套餐内菜品不能直接删除
2.删除对应的菜品对应的口味表也要删除
controller
service
对应涉及到根据ID查询的mapper就不放图片了,也用不到xml文件
像根据id查询菜品,根据id删除菜品,还有口味表中的根据菜品id删除口味都简单,直接注解实现即可
mapper
因为要根据菜品的id查询套餐的id
setmealmapper
设计根据id回显和修改操作
不仅涉及菜品表还涉及菜品口味表
controller
service
id获取菜品信息
修改菜品信息
注意:这里修改口味表情况比较多,我们就用事务注解+删除原口味+新增口味的方法完成
mapper
用到的基本都是之前定义的
就新增这个修改菜品基本信息的