各个业务表中都包含着创建时间,创建人等公共字段导致出现很多冗余代码,若后期需要变更,维护起来会比较麻烦。
解决方法:通过操作类型先将字段进行区分,通过面向切面编程统一拦截mapper而后统一进行赋值,但是并不需要拦截所有方法,所以需要对需要被拦截的方法添加注解
自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
public void autoFill(JoinPoint joinPoint){
//获取当前被拦截方法上的数据库操作类型
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) {
throw new RuntimeException(e);
}
} 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) {
throw new RuntimeException(e);
}
}
}
在Mapper的方法上加入AutoFill 注解
为了防止上传的图片名称重复覆盖其他图片文件,在上传时用uuid随机生成拼接图片后缀可避免此问题
public Result<String> upload(MultipartFile file){
log.info("文件上传:{}",file);
try {
//原始文件名
String originalFilename = file.getOriginalFilename();
//截取原始文件名的后缀 xxxxx.png
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//构造新的文件名 uuid
String objectName = UUID.randomUUID().toString() + extension;
//文件请求路径
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return Result.success(filePath);
} catch (IOException e) {
log.error("文件上传失败:{}",e);
}
涉及多表操作使用逻辑外键,在所定义的具有原子性方法上需要添加@Transactional注解,并在启动项里开启事务注解
在从表中插入数据时需要获取主表的主键值,通过useGeneratedKeys="true"返回sql语句执行后的主键值 keyProperty="id"赋给id
这时就可以在方法调用完后通过对象的get方法获取值