利用切面编程进行实现,话不都说,直接上代码:
第一步:首先创建一个公共类
package com.qcf.example.domain.base; import com.fasterxml.jackson.annotation.JsonFormat; public abstract class BaseEntity { /** * 创建人 */ private String createBy; /** * 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private String createTime; /** * 更新人 */ private String updateBy; /** * 更新时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private String updateTime; /** * 逻辑删除标志 */ private boolean isDelete; public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } public String getUpdateTime() { return updateTime; } public void setUpdateTime(String updateTime) { this.updateTime = updateTime; } public boolean isDelete() { return isDelete; } public void setDelete(boolean delete) { isDelete = delete; } }
第二步:自定义枚举,定义枚举类别
public enum OperationType { /** * 更新操作 */ UPDATE, /** * 插入操作 */ INSERT }
第三步:需要先自定义注解,在自定义注解之前需要导入依赖
依赖如下:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>
注解实现:
@Target(ElementType.METHOD) // 只能加载方法上 @Retention(RetentionPolicy.RUNTIME) // 固定写法 public @interface AutoFillBaseEntity { //枚举,数据库操作类型:UPDATE INSERT OperationType value(); }
第四步:切面实现:
这里注意的是,我的共有字段抽取出来作为一个基类,其余实体类都是继承这个基类,因此在调取方法的时候,需要先调用getSuperclass()方法,然后再调用getDeclaredMethod()方法,例如:
entity.getClass().getSuperclass().getDeclaredMethod("setCreateTime", String.class);
所有代码实现:
@Component @Aspect public class AutoFillBaseEntityAspect { /** * 自定义日期格式 */ private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * 切入点,指定拦截 mapper接口中带有AutoFillBaseEntity注解的方法 */ @Pointcut("execution(* com.qcf.warehouse.mapper.*.*(..)) && @annotation(com.qcf.warehouse.ensemble.annotation.AutoFillBaseEntity)") public void autoFillPointCut() { } /** * 前置通知,在通知中进行公共字段的赋值 */ @Before("autoFillPointCut()") public void autoFill(JoinPoint joinPoint) { //获取到当前被拦截的方法上的数据库操作类型 //方法签名对象 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //获得方法上的注解对象 AutoFillBaseEntity autoFillBaseEntity = signature.getMethod().getAnnotation(AutoFillBaseEntity.class); //获得数据库操作类型 , 更新 或者 插入 OperationType operationType = autoFillBaseEntity.value(); //获取到当前被拦截的方法的参数--实体对象 Object[] args = joinPoint.getArgs(); if (args == null || args.length == 0) { return; } Object entity = args[0]; //根据当前不同的操作类型,为对应的属性通过反射来赋值 if (operationType == OperationType.INSERT) { try { Method setCreateTime = entity.getClass().getSuperclass().getDeclaredMethod("setCreateTime", String.class); Method setCreateBy = entity.getClass().getSuperclass().getDeclaredMethod("setCreateBy", String.class); Method setUpdateTime = entity.getClass().getSuperclass().getDeclaredMethod("setUpdateTime", String.class); Method setUpdateBy = entity.getClass().getSuperclass().getDeclaredMethod("setUpdateBy", String.class); //通过反射为对象属性赋值 setCreateTime.invoke(entity, sdf.format(new Date())); setCreateBy.invoke(entity, "admin"); setUpdateTime.invoke(entity, sdf.format(new Date())); setUpdateBy.invoke(entity, "admin"); } catch (Exception e) { e.printStackTrace(); } } if (operationType == OperationType.UPDATE) { //为2个公共字段赋值 try { Method setUpdateTime = entity.getClass().getSuperclass().getDeclaredMethod("setUpdateTime", String.class); Method setUpdateBy = entity.getClass().getSuperclass().getDeclaredMethod("setUpdateBy", String.class); //通过反射为对象属性赋值 setUpdateTime.invoke(entity, sdf.format(new Date())); setUpdateBy.invoke(entity, "admin"); } catch (Exception e) { e.printStackTrace(); } } }
第五步:在mapper层接口上添加自定义的注解
注解这么添加,添加就是insert , 更新就是 update
第六步:测试,验证最终实现结果
数据库显示结果:
成功插入!!!!!