最近在使用mybatis的时候发现一个问题,就是好多的时候保存实体的时候,都要set create 和update,这样很麻烦,有没有可能类似jap 使用注解自动生成。jpa 的注解原理也拦截sql ,把sql 里面的参数绑定给修改一下。
了解了原理,我们也就自己可以可以自己仿照jpa 实现一下了。
先自定义两个注解@createDate,@updateDate
项目原理,使用mybatis 的拦截器,拦截Executor,的update 方法,
里面 两个参数
根据MappedStatement 获取sql 的注解枚举类型, Object 是入参, 在根据入参 object 获取属性列表,看属性上面是否存在 自定义的注解,不同的注解使用场合不同,在用反射给filed set值。
看一下代码
自定义拦截器
@Intercepts({
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
public class DatePlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Exception {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
// 获取 SQL 命令
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
// 获取参数
Object parameter = invocation.getArgs()[1];
List<ParameterMapping> parameterMappings = mappedStatement.getParameterMap().getParameterMappings();
// 获取私有成员变量
Field[] declaredFields = parameter.getClass().getDeclaredFields();
// 插入要修改两个值
for (Field field : declaredFields) {
if (SqlCommandType.INSERT.equals(sqlCommandType)) {
if (!ObjectUtils.isEmpty(field.getAnnotation(CreateDate.class))) {
field.setAccessible(true);
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
if (!ObjectUtils.isEmpty(field.getAnnotation(UpdateDate.class))) {
field.setAccessible(true);
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
}
// update 只要修改一个值
if (SqlCommandType.UPDATE.equals(sqlCommandType)) {
if (!ObjectUtils.isEmpty(field.getAnnotation(UpdateDate.class))) {
field.setAccessible(true);
field.set(parameter, new Timestamp(System.currentTimeMillis()));
}
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
实体:
现在把
这个插件加入mybatis 的配置中。
一般情况下我们是这样配置的
但是这样是有问题的,我们启动看一下
类型转换错误,这是因为他要的是类mybatis.configuration.interceptors 不是字符串,
我们看一下mybatis 官网
我们只要声明他是一个bean会自动注入的。
我们来写一个测试类
启动项目运行一下,别忘记了
打印sql
启动调用一下接口
creatdate 和updatedate 没有值, 在把实体的注解加上
再跑一下