updateTime 没有被拦截器更新到?

161 阅读1分钟

前言

最近小杨哥找到我说,生产环境有一条问题数据没有更新时间,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拦截器,每个开发还是要明白它在什么情况生效,什么情况不生效还是要清楚的。不然就会出现有些地方开头我同事那种情况