千家信息网

如何实现MyBatis自定义SQL拦截器

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"如何实现MyBatis自定义SQL拦截器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何实现MyBatis自定义SQL拦截器"吧!定义
千家信息网最后更新 2026年11月03日如何实现MyBatis自定义SQL拦截器

本篇内容主要讲解"如何实现MyBatis自定义SQL拦截器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何实现MyBatis自定义SQL拦截器"吧!

定义是否开启注解

定义是否开启注解, 主要做的一件事情就是是否添加 SQL 拦截器。

// 全局开启@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import(MyBatisSqlInterceptorConfiguration.class)public @interface EnableSqlInterceptor {}// 自定义注解@Target({ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface DataScope {}

注册SQL 拦截器

注册一个 SQL 拦截器,会对符合条件的 SQL 查询操作进行拦截。

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

处理逻辑

在处理逻辑中,我主要是做一个简单的 limit 1 案例,如果是自己需要做其他的逻辑需要修改

@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 Logger LOGGER = LoggerFactory.getLogger(MyBatisInterceptor.class);    @Override    public Object intercept(Invocation invocation) throws Throwable {        // TODO Auto-generated method stub        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];        }        DataScope dataScope = getDataScope(ms);        if (Objects.nonNull(dataScope)) {            String origSql = boundSql.getSql();            log.info("origSql : {}", origSql);            // 组装新的 sql            // todo you weaving business            String newSql = origSql + " limit 1";            // 重新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);            }        }        LOGGER.info("mybatis intercept sql:{},Mapper方法是:{}", boundSql.getSql(), ms.getId());        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();    }    private DataScope getDataScope(MappedStatement mappedStatement) {        String id = mappedStatement.getId();        // 获取 Class Method        String clazzName = id.substring(0, id.lastIndexOf('.'));        String mapperMethod = id.substring(id.lastIndexOf('.') + 1);        Class clazz;        try {            clazz = Class.forName(clazzName);        } catch (ClassNotFoundException e) {            return null;        }        Method[] methods = clazz.getMethods();        DataScope dataScope = null;        for (Method method : methods) {            if (method.getName().equals(mapperMethod)) {                dataScope = method.getAnnotation(DataScope.class);                break;            }        }        return dataScope;    }    @Override    public Object plugin(Object target) {        // TODO Auto-generated method stub        LOGGER.info("MysqlInterCeptor plugin>>>>>>>{}", target);        return Plugin.wrap(target, this);    }    @Override    public void setProperties(Properties properties) {        // TODO Auto-generated method stub        String dialect = properties.getProperty("dialect");        LOGGER.info("mybatis intercept dialect:>>>>>>>{}", dialect);    }    /**     * 定义一个内部辅助类,作用是包装 SQL     */    class BoundSqlSource implements SqlSource {        private BoundSql boundSql;        public BoundSqlSource(BoundSql boundSql) {            this.boundSql = boundSql;        }        public BoundSql getBoundSql(Object parameterObject) {            return boundSql;        }    }}

如何使用

我们在 XXXMapper 中对应的数据操作方法只要加入 @DataScope 注解即可。

@Mapperpublic interface OrderMapper {   @Select("select 1 ")   @DataScope   Intger selectOne();}

到此,相信大家对"如何实现MyBatis自定义SQL拦截器"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

拦截器 注解 逻辑 查询 方法 内容 参数 处理 学习 实用 更深 事情 作用 全局 兴趣 实用性 实际 对象 就是 操作简单 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京路客互联网科技有限公司 美国互联网科技巨头监管 互联网金融公司科技 平安科技 互联网 善班互联网科技 深圳齐家互联网科技 掌上梦互联网科技 中国互联网金融科技基金 深圳互联网科技怎么样 上海电发互联网科技有限公司 互联网科技与管理 黑科技闪耀互联网之光 湖南一路畅行互联网科技 中国互联网十大科技股排名 佛山市翊博互联网络科技有限公司 工业互联网展湾科技股份有限公司 滨湖区互联网智能科技产品有哪些 云鲸互联网络科技有限公司 江苏互联网智能科技产品出厂价 科技互联网经济论坛 盈实互联网科技 银优互联网科技有限公司 腾讯科技 互联网女皇 润盈互联网科技 科技赋能互联网健康 西藏七维空间互联网科技有限公司 民营互联网公司国防科技 版纳互联网科技选哪家 张家口科技产业互联网平台 科技互联网专业务虚会材料
0