mybatisplus interceptor

本文详细介绍了Mybatis拦截器如何实现实体数据的动态改变,包括分页插件、逻辑删除设置、自定义SQL拦截器,以及打印控制台SQL并填充参数。展示了如何配置分页、逻辑删除规则,并提供了一个自定义Interceptor示例,用于自动填充创建人信息和时间戳。
摘要由CSDN通过智能技术生成
1
mybatis 拦截器,通过拦截4大对象的方法的执行,完成相关数据的动态改变。

Executor :执行器
StatementHandler :编译器
ParameterHandler :sql参数处理器
ResultSetHandler :结果集处理

插件原理:
4大对象的每个对象创建时都会经过 interceptorChain.pluginAll(),拦截每个插件,经过每个插件的plugin()方法,目的就是给4大对象每个都创建代理。

2.分页插件
com.baomidou.mybatisplus.plugins.paginationInterceptor
使用:
@Configuration
public class MybatisPlusConfig {
    //将自定义对象交给Spring容器管理
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}

3.逻辑删除
--------
yml:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为0)

User 实体:
 @TableLogic
    private Integer deleted;

执行删除就会变为update,查询也会默认加上 where deleted = 0








4.自定义sql拦截器,为创建时间,创建人,修改时间,修改人,赋默认值

自定义拦截器
@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})}) // 此处 update 包含  增加, 修改操作
public class MyInterceptor implements Interceptor {
    /**
     * 获取用户缓存信息
     */
    public User getLoginUser() {
        try{
            return UserInfo.getUserInfo(); // 在项目中通过线程或框架获取用户数据
        }catch (Exception e){
            return new User();
        }
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // TODO Auto-generated method stub
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];
        if (parameter == null) {
            return invocation.proceed();
        }
        //sql命令类型为插入,自动注入创建人信息
        if (SqlCommandType.INSERT == sqlCommandType) {
            User userEntity = getLoginUser();
            if(null == userEntity){
                return null;
            }
            Field[] fields = parameter.getClass().getDeclaredFields();
            for (Field field : fields) {
                log.info("------field.name------" + field.getName());
                try {
                    // 注入创建用户id
                    if ("createUser".equals(field.getName())) {
                        field.setAccessible(true);
                        Object local_createBy = field.get(parameter);
                        field.setAccessible(false);
                        if (local_createBy == null || local_createBy.equals("")) {
                            if (userEntity != null) {
                                // 登录人账号
                                field.setAccessible(true);
                                field.set(parameter, Long.parseLong(userEntity.getUserId().toString()));
                                //field.set("updateBy", userEntity.getUsername());
                                field.setAccessible(false);
                            }
                        }

                    }
                    // 注入创建时间
                    if ("createTime".equals(field.getName())) {
                        field.setAccessible(true);
                        Object local_createDate = field.get(parameter);
                        field.setAccessible(false);
                        if (local_createDate == null || local_createDate.equals("")) {
                            field.setAccessible(true);
                            field.set(parameter, System.currentTimeMillis());
                            //field.set("updateTime", new Date());
                            field.setAccessible(false);
                        }
                    }
                } catch (Exception e) {
                }
            }
        }
        //sql命令类型为更新,自动注入修改人信息
        if (SqlCommandType.UPDATE == sqlCommandType) {
            User userEntity = getLoginUser();
            if(null == userEntity){
                return null;
            }
            Field[] fields = parameter.getClass().getDeclaredFields();
            for (Field field : fields) {
                log.info("------field.name------" + field.getName());
                try {
// 注入创建用户id
                    if ("updateUser".equals(field.getName())) {
                        field.setAccessible(true);
                        Object local_createBy = field.get(parameter);
                        field.setAccessible(false);
                        if (local_createBy == null || local_createBy.equals("")) {
                            if (userEntity != null) {
                                // 登录人账号
                                field.setAccessible(true);
                                field.set(parameter, Long.parseLong(userEntity.getUserId().toString()));
                                field.setAccessible(false);
                            }
                        }
                    }
// 注入创建时间
                    if ("updateTime".equals(field.getName())) {
                        field.setAccessible(true);
                        Object local_createDate = field.get(parameter);
                        field.setAccessible(false);
                        if (local_createDate == null || local_createDate.equals("")) {
                            field.setAccessible(true);
                            field.set(parameter, System.currentTimeMillis());
                            field.setAccessible(false);
                        }
                    }
                } catch (Exception e) {
                }
            }
        }
        return invocation.proceed();
    }

}
注册插件
@Configuration
public class MybatisPlusConfig {
    //分页插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    //自动填充 创建人,创建时间,修改人,修改时间
    @Bean
    public Boolean setAutoFillValueInterceptor(SqlSessionFactory sqlSessionFactory) {
        org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
        configuration.addInterceptor(new MyInterceptor());
        return Boolean.TRUE;
    }

}

每个实体都要加     
	private Long createUser;
    private Long createTime;
    private Long updateUser;
    private Long updateTime;

对应数据库
在这里插入图片描述


5.打印控制台sql并自动填充where 参数

@Intercepts(
        {
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
                @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        }
)
@Log4j2
public class MybatisSqlLogInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object proceed = invocation.proceed();
        // 获取xml中的一个select/update/insert/delete节点,是一条SQL语句
        MappedStatement mappedStatement = (MappedStatement)invocation.getArgs()[0];
        Object parameter = null;
        // 获取参数,if语句成立,表示sql语句有参数,参数格式是map形式
        if (invocation.getArgs().length > 1) {
            parameter = invocation.getArgs()[1];
        }
        // BoundSql就是封装myBatis最终产生的sql类
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        // 获取节点的配置
        Configuration configuration = mappedStatement.getConfiguration();
        // 获取到最终的sql语句
        String sql = showSql(configuration, boundSql);
        System.err.println("mybatis sql: " + sql);
        return proceed;
    }

    /**
     * 如果参数是String,则添加单引号,
     * 如果是日期,则转换为时间格式器并加单引号;
     * 对参数是null和不是null的情况作了处理
     */
    private static String getParameterValue(Object obj) {
        String value;
        if (obj instanceof String) {
            value = "'" + obj.toString() + "'";
        } else if (obj instanceof Date) {
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,
                    DateFormat.DEFAULT, Locale.CHINA);
            value = "'" + formatter.format(new Date()) + "'";
        } else {
            if (obj != null) {
                value = obj.toString();
            } else {
                value = "";
            }
        }
        return value;
    }

    /**
     * 进行?的替换
     *
     * @param configuration
     * @param boundSql
     * @return
     */
    public String showSql(Configuration configuration, BoundSql boundSql) throws NoSuchFieldException, IllegalAccessException {
        // 获取参数
        Object parameterObject = boundSql.getParameterObject();
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        // sql语句中多个空格都用一个空格代替
        String sql = getRealSql().replaceAll("[\\s]+", " ");
        if (parameterObject != null) {
            // 获取类型处理器注册器,类型处理器的功能是进行java类型和数据库类型的转换
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            // 如果根据parameterObject.getClass()可以找到对应的类型,则替换
            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?",
                        Matcher.quoteReplacement(getParameterValue(parameterObject)));

            } else {
                // MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作
                MetaObject metaObject = configuration.newMetaObject(parameterObject);
                for (ParameterMapping parameterMapping : parameterMappings) {
                    String propertyName = parameterMapping.getProperty();
                    if (metaObject.hasGetter(propertyName)) {
                        Object obj = metaObject.getValue(propertyName);
                        sql = sql.replaceFirst("\\?",
                                Matcher.quoteReplacement(getParameterValue(obj)));
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
                        // 该分支是动态sql
                        Object obj = boundSql.getAdditionalParameter(propertyName);
                        sql = sql.replaceFirst("\\?",
                                Matcher.quoteReplacement(getParameterValue(obj)));
                    } else {
                        // 打印出缺失,提醒该参数缺失并防止错位
                        sql = sql.replaceFirst("\\?", "缺失");
                    }
                }
            }
        }
        return sql;
    }

    /**
     * 获取真实sql, mybatis将其存在ThreadLocal中
     * @return
     * @throws IllegalAccessException
     * @throws NoSuchFieldException
     */
    private String getRealSql() throws IllegalAccessException, NoSuchFieldException {
        Field field = ErrorContext.class.getDeclaredField("sql");
        field.setAccessible(true);
        Object sql = field.get(ErrorContext.instance());
        if (sql != null) {
            return sql.toString();
        }
        return "";
    }


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

    @Override
    public void setProperties(Properties properties) {
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值