MyBatis-Plus实现SQL执行前统一处理添加只读标识等注释

背景

由于项目中采用的DRDS数据库,为了实现查询语句在读库上执行,我们需要在sql前拼接/!TDDL:SALVE*/,对于以前的老项目,可以选择在代码里手动拼接的方式,但是对于我们采用了MyBatis-Plus插件的项目再采用xml中每个sql前拼接的方式,显得有那么一些些不和谐。因此我们可以利用MyBatis-Plus官方提供的能力,在sql执行前拦截,然后拼接我们想添加的任何注释内容

实现

首先我们需要引入MyBatis-Plus的pom文件,有版本限制,需要大于等于以下版本。

1、引入pon

xml 复制代码
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

2、自定义MyBatis的拦截器接口org.apache.ibatis.plugin.Interceptor

java 复制代码
@Slf4j
public class MyBatisPlusSqlAnnotationInterceptor implements InnerInterceptor {
	// 我们需要添加的注释
    private static final String READ_FLAG = "/!TDDL:SLAVE*/";

    // 添加环境变量控制注释是否启用
    private boolean readOnlyFlag;


    public MyBatisPlusSqlAnnotationInterceptor(boolean readOnlyFlag) {
        this.readOnlyFlag = readOnlyFlag;
    }

    @Override
    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
            PluginUtils.MPStatementHandler handler = PluginUtils.mpStatementHandler(sh);
            MappedStatement ms = handler.mappedStatement();
            SqlCommandType sct = ms.getSqlCommandType();
            if (sct == SqlCommandType.SELECT && readOnlyFlag) {
                    BoundSql boundSql = handler.boundSql();
                    String sql = boundSql.getSql();
                    sql = READ_FLAG + sql;
                    try {
                        Field field = boundSql.getClass().getDeclaredField("sql");
                        field.setAccessible(true);
                        field.set(boundSql, sql);
                    } catch (NoSuchFieldException e) {
                        log.error("NoSuchFieldException:", e);
                    } catch (IllegalAccessException e) {
                        log.error("IllegalAccessException:", e);
                    }
                }
    }
}

3、配置MyBatis-Plus配置

java 复制代码
@Configuration
public class MybatisPlusConfig {
	// 配置文件控制执行与否
    @Value(value = "${flag.readOnly:true}")
    private boolean flagReadOnly;

    /**
     * 内置插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        // 增加我们的自定义插件
        interceptor.addInnerInterceptor(new MyBatisPlusSqlAnnotationInterceptor(flagReadOnly));
        return interceptor;
    }

    /**
     * Map下划线自动转驼峰
     */
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return i -> i.setObjectWrapperFactory(new MybatisMapWrapperFactory());
    }

}

参考

https://blog.csdn.net/weixin_42182797/article/details/130530899

相关推荐
倔强的石头_14 小时前
《Kingbase护城河》——猎捕慢查询:执行计划的微观解析与索引调优实战
数据库
SelectDB16 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
Flittly17 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了17 小时前
Java 生成二维码解决方案
java·后端
人活一口气1 天前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP1 天前
Vibe Coding -- 完整项目案例实操
java
荣码1 天前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing1 天前
Google第三方授权登录
java·后端·程序员
明月光8181 天前
从一行 @Builder 说起:重新拾起 Java 的 Lombok、注解与 Builder 模式
java
考虑考虑1 天前
Mybatis实现批量插入
java·后端·mybatis