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

相关推荐
vennnnnnnnnnnnnn10 小时前
Excel 导入原文保留与内联排名配置问题复盘
前端·数据库·excel
dunky10 小时前
副本机制与 ISR 设计:为什么 Kafka 这么快又这么可靠
java
Tirzano10 小时前
批量查询在线成员对应节点redis
数据库·redis·junit
夕除10 小时前
spring boot 9
java·mysql·spring
执明wa10 小时前
从 T 到协变逆变
java·开发语言·数据结构
夜雪闻竹10 小时前
语义搜索实战:从关键词到向量检索
数据库·知识图谱·ai编程·knowledge graph
XiYang-DING10 小时前
【Java EE】 TCP—异常情况处理
java·tcp/ip·java-ee
lianghyan10 小时前
List.stream().min
java·开发语言
GreatSQL社区10 小时前
解决 GreatSQL 报错:存储过程字符集排序规则不兼容问题
数据库
老码观察11 小时前
MySQL 慢 SQL 治理实战:从索引原理到真实踩坑
sql·mysql