方法一:Mybatis-plus实现
步骤一:在实体类的属性上使用@TableField注解指定自动填充的策略
参数可为
1:@TableField(fill = FieldFill.INSERT) 时机:在插入数据的时候
2:@TableField(fill = FieldFill.UPDATE) 时机:在更新数据的时候
3:@TableField(fill = FieldFill.INSERT_UPDATE) 时机:在插入或更新数据的时候
示例如图:
步骤二: 创建一个类,实现(implements)MetaObjectHandler接口并重写insertFill(MetaObject metaObject)和updateFill(MetaObject metaObject)方法。
这两个方法分别对应着属性自动填充的时机。插入数据的时候,和更新数据的时候。
接着,在重写的方法里写语句:metaObject.setValue(String name, Object value);第一个参数对应着实体类属性的名称,第二个参数对应着属性自动填充的值。
示例如图:
最后记得在类上面加上@Component注解,把这个类交给Spring管理。
方法二:(AOP + 反射)实现
步骤一:自定义枚举FieldFill,定义数据库操作类型
public enum FieldFill {
INSERT, //插入操作
UPDATE; //更新操作
private FieldFill() {
}
}
步骤二:自定义注解AutoFill,后续为被该注解标记的方法执行自动填充
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TableField {
FieldFill fill();
}
步骤三:定义通知类,切入点,切面,通知
@Aspect
@Component
public class AutoFillAspect {
//定义切入点
@Pointcut("execution(* com.aurora.aop.mapper.*.*(..)) && @annotation(com.aurora.aop.annotation.TableField)")
public void autoFillPoinCut(){}
//定义通知,因为insert和update之前,故前置通知
@Before("autoFillPoinCut()")
public void autoFill(JoinPoint joinPoint){
//获取到当前被拦截的方法上的数据库操作类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
TableField tableField = signature.getMethod().getAnnotation(TableField.class);
FieldFill fillType = tableField.fill();
//获取到当前被拦截的方法的方法参数,即实体类
Object[] args = joinPoint.getArgs();
Object entity = args[0];
LocalDateTime now = LocalDateTime.now();
//根据不同的操作类型
if (fillType == FieldFill.INSERT) {
//为公共字段赋值
try {
Method setCreatTime = entity.getClass().getDeclaredMethod("setCreatTime",
LocalDateTime.class);
setCreatTime.invoke(entity,now);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
以实体类User举例:
@Data
public class User {
private String username;
private String password;
private LocalDateTime creatTime;
}
UserMapper:
@Mapper
public interface UserMapper {
@TableField(fill = FieldFill.INSERT)
@Insert("insert into user (username, password, creat_time) values (#{username}, #{password}, #{creatTime})")
void insert(User user);
}
在insert方法中添加我们自定义的注解@TableField(fill = FieldFill.INSERT),当运行到这个方法之前,在我们的通知中会把参数中的user的公共字段creatTime字段赋值。
最后测试用例:
@SpringBootTest
class AopApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void testAOP() {
User user = new User();
user.setUsername("aop");
user.setPassword("666666666");
userMapper.insert(user);
}
}
运行结果:
可以看到,我们并没有为User中的creatTime属性赋值,但是实现了字段填充!