mybatis的sql拦截器应用

mybatis的sql拦截器在项目上线前后用于检测SQL性能,防止全表查询和大对象产生。本文通过示例介绍了如何实现拦截器,包括输出SQL耗时、拦截特定查询等,对测试和生产环境有显著效果。
摘要由CSDN通过智能技术生成

mybatis的sql拦截器应用

前言

在项目上线前的开发及调试中,都需要清楚的知道每条sql的用时来避免在生产环境出现慢查询,甚至对于业务逻辑较复杂的应用,还需防止大对象的产生(比如千万级别的集合),此时我们完全可以使用mybatis的sql拦截器来实现以上效果。下面是一个sql拦截器的简单记录,以加深印象。

作用

拦截器实现的功能有:

  1. 拦截全表查询sql(可配置白名单)
  2. 防止大对象的产生(集合大于4万的sql进行告警,并不拦截)
  3. 输出完整的sql
  4. 输出sql的大约用时

示例代码

一、引入相关mybatis的maven

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>

//用于解析sql
<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>0.9.5</version>
</dependency>

(具体拦截器配置省略,如不清楚该学习了)

二、sql拦截器具体实现

@Slf4j
@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}
)
@Component
public class SqlInterceptor implements Interceptor {
    /**
     * 全表扫的白名单,接入了disconf,也可以hardcode字符串
     */
    @Autowired(required = false)
    private SqlIntercepterWhiteListConf sqlIntercepterWhiteListConf;

    /**
     * DQL最大返回值
     */
    private Integer allowMaxReturn;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        EmailPool emailPool = EmailPool.getInstance();
        String whiteList = sqlIntercepterWhiteListConf.getSqlWhiteList();
        Object result;
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object parameter = invocation.getArgs()[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        String sql = boundSql.getSql();
        Map<String, String> whereResult = getWhere(sql);
        String where = whereResult.get("success");
        String join = whereResult.get("join");
        if (Objects.nonNull(where) && StringUtils.isBlank(join)) {
            where = where.replace("1 = 1", "");
            String tableName = getMainTableName(sql);
            if (StringUtils.isNotEmpty(whiteList) && !StringUtils.containsIgnoreCase(whiteList, tableName) && StringUtils.isBlank(where)) {
                String emailMes = "vin-sql拦截器【已拦截】:出现不在配置内的全表扫描:" + tableName + "--->" + beautifySql(sql);
                log.warn(emailMes);
                emailPool.putEmailToQueue(emailMes);
    //                try {
    //                    EmailUtil.sendMessage(emailMes, "tech-vin@qipeipu.com");
    //                } catch (Exception e) {
    //                    log.warn("vin-sql拦截器发送邮件失
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值