ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

springboot项目中添加mybatis自定义sql拦截器

2022-05-24 16:33:58  阅读:207  来源: 互联网

标签:拦截器 springboot 自定义 org boundSql ms sql import class


import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

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

/**
 * @version 1.0
 * @date 2022/5/7 14:42
 * @since : JDK 11
 */
@Slf4j
@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}),
        }
)
public class MyBatisInterceptor implements Interceptor {

    private static final List<String> METHOD_LIST = Arrays.asList("list", "query", "find", "count", "select");

    /**
     * 白名单表
     */
    private static final  List<String> WHITE_LIST_TABLE = Arrays.asList("");

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameter = args[1];
        RowBounds rowBounds = (RowBounds) args[2];
        ResultHandler resultHandler = (ResultHandler) args[3];
        Executor executor = (Executor) invocation.getTarget();
        CacheKey cacheKey;
        BoundSql boundSql;
        //由于逻辑关系,只会进入一次
        if (args.length == 4) {
            //4 个参数时
            boundSql = ms.getBoundSql(parameter);
            cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);
        } else {
            //6 个参数时
            cacheKey = (CacheKey) args[4];
            boundSql = (BoundSql) args[5];
        }
        String origSql = boundSql.getSql().replaceAll("\\s", " ").toLowerCase();
        // 组装新的 sql
        String newSql = handler(ms.getId(), origSql);
        // 重新new一个查询语句对象
        BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), newSql,
                boundSql.getParameterMappings(), boundSql.getParameterObject());
        // 把新的查询放到statement里
        MappedStatement newMs = newMappedStatement(ms, new BoundSqlSource(newBoundSql));
        for (ParameterMapping mapping : boundSql.getParameterMappings()) {
            String prop = mapping.getProperty();
            if (boundSql.hasAdditionalParameter(prop)) {
                newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
            }
        }

        args[0] = newMs;
        if (args.length == 6) {
            args[5] = newMs.getBoundSql(parameter);
        }
        return invocation.proceed();
    }

    private MappedStatement newMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
        MappedStatement.Builder builder = new
                MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        if (ms.getKeyProperties() != null && ms.getKeyProperties().length > 0) {
            builder.keyProperty(ms.getKeyProperties()[0]);
        }
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.resultSetType(ms.getResultSetType());
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }

    @Override
    public Object plugin(Object target) {
        log.info("MysqlInterceptor plugin>>>>>>>{}", target);
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        String dialect = properties.getProperty("dialect");
        log.info("mybatis intercept dialect:>>>>>>>{}", dialect);
    }

    /**
     * 定义一个内部辅助类,作用是包装 SQL
     */
    class BoundSqlSource implements SqlSource {
        private BoundSql boundSql;

        public BoundSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }

        @Override
        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }

    }


    /**
     * 模块级处理查询sql拼装未删除字段
     */
    private String handler(String mapperId, String sql) {
        for (String m : METHOD_LIST) {
            if (mapperId.toLowerCase().contains(m)) {
                if (sql.contains("is_del")) {
                    return sql;
                } else {
                    String tableAlias;
                    String[] split;
                    if (sql.contains("join")) {
                        split = ReUtil.findAll("from(.*?)left\\s+join", sql, 1).get(0).trim().split("\\s");
                    } else {
                        split = ReUtil.findAll("from(.*?)where", sql, 1).get(0).trim().split("\\s");
                    }
                    if (split.length > 1) {
                        tableAlias = split[split.length - 1];
                    } else {
                        tableAlias = split[0];
                    }
                    if (sql.contains("limit")) {
                        int index = sql.indexOf("limit");
                        String sqlPrefix = StrUtil.sub(sql, 0, index);
                        String sqlSuffix;
                        if (sql.contains("where")) {
                            sqlSuffix = " and " + tableAlias + ".is_del = 0 " + StrUtil.sub(sql, index, sql.length());
                        } else {
                            sqlSuffix = " where " + tableAlias + ".is_del = 0 " + StrUtil.sub(sql, index, sql.length());
                        }
                        return sqlPrefix + sqlSuffix;
                    } else {
                        if (sql.contains("where")) {
                            return sql + " and " + tableAlias + ".is_del = 0 ";
                        } else {
                            return sql + " where " + tableAlias + ".is_del = 0 ";
                        }
                    }
                }
            }
        }
        return sql;
    }
}

import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author JHL
 * @version 1.0
 * @date 2022/5/7 14:41
 * @since : JDK 11
 */
@Component
public class MyBatisSqlInterceptorConfiguration implements ApplicationContextAware {

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SqlSessionFactory sqlSessionFactory = applicationContext.getBean(SqlSessionFactory.class);
        sqlSessionFactory.getConfiguration().addInterceptor(new MyBatisInterceptor());
    }
}

参考:MyBatis 自定义 SQL 拦截器

标签:拦截器,springboot,自定义,org,boundSql,ms,sql,import,class
来源: https://www.cnblogs.com/hhddd-1024/p/16305994.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有