MyBatis拦截器怎么动态替换表名
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容主要讲解"MyBatis拦截器怎么动态替换表名",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"MyBatis拦截器怎么动态替换表名"吧!一、Myba
千家信息网最后更新 2026年11月02日MyBatis拦截器怎么动态替换表名
本篇内容主要讲解"MyBatis拦截器怎么动态替换表名",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"MyBatis拦截器怎么动态替换表名"吧!
一、Mybatis Interceptor 拦截器接口和注解
简单的说就是mybatis在执行sql的时候,拦截目标方法并且在前后加上我们的业务逻辑。实际上就是加@Intercepts注解和实现org.apache.ibatis.plugin.Interceptor接口
@Intercepts( @Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} ))public interface Interceptor { //主要重写这个方法、实现我们的业务逻辑 Object intercept(Invocation invocation) throws Throwable; //生成代理对象,可以在这里判断是否生成代理对象 Object plugin(Object target); //如果我们拦截器需要用到一些变量参数,可以在这里读取 void setProperties(Properties properties);}二、实现思路
在intercept方法中有参数Invocation对象,里面有3个成员变量和@Signature对应
| 成员变量 | 变量类型 | 说明 |
|---|---|---|
| target | Object | 代理对象 |
| method | Method | 被拦截方法 |
| args | Object[] | 被拦截方法执行所需的参数 |
通过Invocation中的args变量。我们能拿到MappedStatement这个对象(args[0]),传入sql语句的参数Object(args[1])。而MappedStatement是一个记录了sql语句(sqlSource对象)、参数值结构、返回值结构、mapper配置等的一个对象。
sqlSource对象和传入sql语句的参数对象Object就能获得BoundSql。BoundSql的toString方法就能获取到有占位符的sql语句了,我们的业务逻辑就能在这里介入。
获取到sql语句,根据规则替换表名,塞回BoundSql对象中、再把BoundSql对象塞回MappedStatement对象中。最后再赋值给args[0](实际被拦截方法所需的参数)就搞定了
三、代码实现
import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;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.*;/** * @description: 动态替换表名拦截器 * @author: hinotoyk * @created: 2022/04/19 *///method = "query"拦截select方法、而method = "update"则能拦截insert、update、delete的方法@Intercepts({ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})public class ReplaceTableInterceptor implements Interceptor { private final static Map TABLE_MAP = new LinkedHashMap<>(); static { //表名长的放前面,避免字符串匹配的时候先匹配替换子集 TABLE_MAP.put("t_game_partners","t_game_partners_test");//测试 TABLE_MAP.put("t_file_recycle","t_file_recycle_other"); TABLE_MAP.put("t_folder","t_folder_other"); TABLE_MAP.put("t_file","t_file_other"); } @Override public Object intercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); //获取MappedStatement对象 MappedStatement ms = (MappedStatement) args[0]; //获取传入sql语句的参数对象 Object parameterObject = args[1]; BoundSql boundSql = ms.getBoundSql(parameterObject); //获取到拥有占位符的sql语句 String sql = boundSql.getSql(); System.out.println("拦截前sql :" + sql); //判断是否需要替换表名 if(isReplaceTableName(sql)){ for(Map.Entry entry : TABLE_MAP.entrySet()){ sql = sql.replace(entry.getKey(),entry.getValue()); } System.out.println("拦截后sql :" + sql); //重新生成一个BoundSql对象 BoundSql bs = new BoundSql(ms.getConfiguration(),sql,boundSql.getParameterMappings(),parameterObject); //重新生成一个MappedStatement对象 MappedStatement newMs = copyMappedStatement(ms, new BoundSqlSqlSource(bs)); //赋回给实际执行方法所需的参数中 args[0] = newMs; } return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } /*** * 判断是否需要替换表名 * @param sql * @return */ private boolean isReplaceTableName(String sql){ for(String tableName : TABLE_MAP.keySet()){ if(sql.contains(tableName)){ return true; } } return false; } /*** * 复制一个新的MappedStatement * @param ms * @param newSqlSource * @return */ private MappedStatement copyMappedStatement (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(String.join(",",ms.getKeyProperties())); } 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(); } /*** * MappedStatement构造器接受的是SqlSource * 实现SqlSource接口,将BoundSql封装进去 */ public static class BoundSqlSqlSource implements SqlSource { private BoundSql boundSql; public BoundSqlSqlSource(BoundSql boundSql) { this.boundSql = boundSql; } @Override public BoundSql getBoundSql(Object parameterObject) { return boundSql; } }} 四、运行结果
到此,相信大家对"MyBatis拦截器怎么动态替换表名"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
对象
方法
参数
语句
拦截器
变量
动态
实际
生成
业务
接口
逻辑
代理
内容
就是
成员
时候
注解
结构
学习
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
上海挚品互联网科技有限公司
广州百单互联网科技有限公司
科技互联网产品
互联网科技公司华为
互联网科技巨头监管
互联网科技开发公司
互联网 科技
成都互联网科技公司
华中科技大学互联网
互联网科技大会
互联网科技生活的内容
互联网科技公司有风险吗
健康食品互联网创新科技园项目
迪庆互联网科技招生
企晟互联网信息科技有限公司
济南有互联网科技公司吗
互联网领先科技宣传片
互联网科技包装股
信承诺互联网科技有限公司
中国新注册互联网科技
互联网科技有限公司经营范围
互联网是不是新科技
广州互联网科技公司
互联网之后的科技是什么
承德科技产业互联网发展
江苏互联网智能科技软件
互联网科技股为什么大涨
互联网科技机房
同城互联网络科技
10位科技互联网大佬