美文网首页
mybatis拦截器尝试

mybatis拦截器尝试

作者: c7d122ec46c0 | 来源:发表于2022-04-17 22:42 被阅读0次

    目标

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

    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配置文件增加

    <configuration>
    ------------------省略-----------------------------
       <plugins>
            <plugin interceptor="com.XXX.biz.interceptor.MybatisInterceptor"/>
        </plugins>
    </configuration>
    

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

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

    参考

    mybatis源码解析
    mybatis分页插件

    相关文章

      网友评论

          本文标题:mybatis拦截器尝试

          本文链接:https://www.haomeiwen.com/subject/pjglertx.html