mybatis拦截器尝试

目标

设置一个拦截器设置操作人为当前用户,如果是新增则设置更新时间和创建时间为当前时间,如果是更新则设置更新时间为当前时间

mybatis四大对象

  • Executor:代表执行器,由它调度StatementHandler、ParameterHandler、ResultSetHandler等来执行对应的SQL,其中StatementHandler是最重要的。
  • StatementHandler:作用是使用数据库的Statement(PreparedStatement)执行操作,它是四大对象的核心,起到承上启下的作用,如果我们要做一个分页插件需要在这里改下sql
  • ParameterHandler:是用来处理SQL参数的。
  • ResultSetHandler:是进行数据集(ResultSet)的封装返回处理的。

开始

insert,update,delete 最终都会走向Executor对象的 update 方法,所以我们只需要拦截它就行了。
类MybatisInterceptor

@Intercepts({@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})})
@Slf4j
@SuppressWarnings("rawtypes")
public class MybatisInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Date now = new Date();
       // 这是公司项目中存放用户信息的ThreadLocal工具类,可以自行替换
        Long userWid = Long.parseLong((String) WebContext.getInstance().get(WebContext.USER_WID));
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object object = invocation.getArgs()[1];
        try {
            if(object instanceof Map) {
                Object record = ((Map) object).get("record");
                if(record != null) {
                    //sql类型
                    SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
                    if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                        //插入操作时,自动插入当前时间和操作人
                        setValueNotExist(record, "createTime", now);
                        setValueNotExist(record, "updateTime", now);
                        setValueNotExist(record, "operatorWid", userWid);

                    } else {
                        if (SqlCommandType.UPDATE.equals(sqlCommandType)) {

                            //update时,自动更新update_time 和操作人
                            setValueNotExist(record, "updateTime", now);
                            setValueNotExist(record, "operatorWid", userWid);
                        }
                    }
                }
            }
        }catch (Exception e){
            log.error("mybatisInterceptor error", e);
        }

        return invocation.proceed();

    }
    private void setValueNotExist(Object record, String fieldName, Object value){
        Field field = ReflectUtil.getField(record.getClass(), fieldName);
        if(field != null && ReflectUtil.getFieldValue(record,field) == null) {
            ReflectUtil.setFieldValue(record, fieldName, value);
        }
    }



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

    @Override
    public void setProperties(Properties properties) {

    }

mybatis配置文件增加


------------------省略-----------------------------
   
        
    

这里做的比较简单,默认取的是第一个参数。我们项目使用的是mybatisGenerator生成的代码默认第一个参数就是实体类,如下

如果是自定的mapper文件,代码还需要加很多其他的判断,因此比较好的做法是实体类有个特殊的类名结尾比如entity或者实体类继承某个基类,这样能一下找到需要设置参数的类。

参考

mybatis源码解析
mybatis分页插件

你可能感兴趣的:(mybatis拦截器尝试)