前言
最近小杨哥找到我说,生产环境有一条问题数据没有更新时间,mybaits拦截器会自动更新的啊,而且就这一条数据。于是我去看了一下拦截器的实现,发现确实会有很多情况都更新不到。
拦截器代码
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
String sqlId = mappedStatement.getId();
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
Object parameter = invocation.getArgs()[1];
if (parameter == null) {
return invocation.proceed();
}
if (SqlCommandType.UPDATE == sqlCommandType) {
Field[] fields = null;
if (parameter instanceof ParamMap) {
ParamMap<?> p = (ParamMap<?>) parameter;
String et = "et";
if (p.containsKey(et)) {
parameter = p.get(et);
} else {
parameter = p.get("param1");
}
if (parameter == null) {
return invocation.proceed();
}
fields = oConvertUtils.getAllFields(parameter);
} else {
fields = oConvertUtils.getAllFields(parameter);
}
for (Field field : fields) {
try {
if ("updateTime".equals(field.getName())) {
field.setAccessible(true);
field.set(parameter, new Date());
field.setAccessible(false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return invocation.proceed();
}
能自动更新update_time情况
- 有
et参数,并且et实体存在update_time属性存在,利用反射set更新时间//没错Constants.ENTITY的值就是et,如果entity传的话,更新时间就不会被拦截器set //com.baomidou.mybatisplus.core.mapper.BaseMapper int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); - 没有
et参数,就获取第一个参数的实体,获取update_time属性,利用反色set更新时间//这种手写mapper,第一个参数为实体,也能被拦截器`set`更新时间。并且sql中需要写更新时间的sql update(T entity,T where)
需要手动set更新的情况
除来上面的两种情况,不用手动更新,其他情况都不能被自动set 更新时间
eg:
//1.entity传null
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
//2. 自己写的mapper接口,sql里面没有写更新时间的sql
总结
所以说update拦截器,每个开发还是要明白它在什么情况生效,什么情况不生效还是要清楚的。不然就会出现有些地方开头我同事那种情况