MyBatis修改操作注入动态全局参数

有时候我们在更新字段的时候可能只更新一个状态,但是又需要记录当前的更新人和更新时间,比如:

updateStatus(@Param("id") String id, @Param("status") Integer status);

这个时候又不想创建DO或者DTO,可以添加一个全局的参数注入,把当前用户信息和当前时间注入到当前执行的sql的上下文中

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ReflectUtil;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;

import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

@Intercepts({
        @Signature(type = StatementHandler.class, method = "parameterize", args = {Statement.class})
})
public class InjectGlobalParamInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        if(StatementHandler.class.isAssignableFrom(target.getClass())) {
            RoutingStatementHandler statementHandler = (RoutingStatementHandler) target;
            BoundSql boundSql = statementHandler.getBoundSql();
            BaseStatementHandler delegate = (BaseStatementHandler) ReflectUtil.getFieldValue(statementHandler, "delegate");
            MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");
            SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
            if(SqlCommandType.INSERT == sqlCommandType || SqlCommandType.UPDATE == sqlCommandType || SqlCommandType.DELETE == sqlCommandType) {
                putParamsIfNecessary(boundSql);
            }
        }
        return invocation.proceed();
    }

    private void putParamsIfNecessary(BoundSql boundSql) {
        List parameterMappings = boundSql.getParameterMappings();
        if (parameterMappings != null) {
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    String propertyName = parameterMapping.getProperty();
                    if (Arrays.asList("_G_NOW", "_NOW").contains(propertyName)) {
                        boundSql.setAdditionalParameter(propertyName, DateUtil.date().toString());
                    }
                    if (Arrays.asList("_G_UUID", "_UUID").contains(propertyName)) {
                        boundSql.setAdditionalParameter(propertyName, IdUtil.fastSimpleUUID());
                    }
                }
            }
        }
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

参考源码位置:
Mybatis:

// DefaultParameterHandler
@Override
 public void setParameters(PreparedStatement ps) {
   ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
   List parameterMappings = boundSql.getParameterMappings();
   if (parameterMappings != null) {
     for (int i = 0; i < parameterMappings.size(); i++) {
       ParameterMapping parameterMapping = parameterMappings.get(i);
       if (parameterMapping.getMode() != ParameterMode.OUT) {
         Object value;
         String propertyName = parameterMapping.getProperty();
         if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
           value = boundSql.getAdditionalParameter(propertyName);
         } else if (parameterObject == null) {
           value = null;
         } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
           value = parameterObject;
         } else {
           MetaObject metaObject = configuration.newMetaObject(parameterObject);
           value = metaObject.getValue(propertyName);
         }
         TypeHandler typeHandler = parameterMapping.getTypeHandler();
         JdbcType jdbcType = parameterMapping.getJdbcType();
         if (value == null && jdbcType == null) {
           jdbcType = configuration.getJdbcTypeForNull();
         }
         try {
           typeHandler.setParameter(ps, i + 1, value, jdbcType);
         } catch (TypeException | SQLException e) {
           throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
         }
       }
     }
   }
 }

Mybatis-Plus:

// MybatisParameterHandler
@Override
   @SuppressWarnings("unchecked")
   public void setParameters(PreparedStatement ps) {
       ErrorContext.instance().activity("setting parameters").object(this.mappedStatement.getParameterMap().getId());
       List parameterMappings = this.boundSql.getParameterMappings();
       if (parameterMappings != null) {
           for (int i = 0; i < parameterMappings.size(); i++) {
               ParameterMapping parameterMapping = parameterMappings.get(i);
               if (parameterMapping.getMode() != ParameterMode.OUT) {
                   Object value;
                   String propertyName = parameterMapping.getProperty();
                   if (this.boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
                       value = this.boundSql.getAdditionalParameter(propertyName);
                   } else if (this.parameterObject == null) {
                       value = null;
                   } else if (this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) {
                       value = parameterObject;
                   } else {
                       MetaObject metaObject = this.configuration.newMetaObject(this.parameterObject);
                       value = metaObject.getValue(propertyName);
                   }
                   TypeHandler typeHandler = parameterMapping.getTypeHandler();
                   JdbcType jdbcType = parameterMapping.getJdbcType();
                   if (value == null && jdbcType == null) {
                       jdbcType = this.configuration.getJdbcTypeForNull();
                   }
                   try {
                       typeHandler.setParameter(ps, i + 1, value, jdbcType);
                   } catch (TypeException | SQLException e) {
                       throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
                   }
               }
           }
       }
   }

你可能感兴趣的:(MyBatis修改操作注入动态全局参数)