SQL server使用MybatisPlus查询SQL加上WITH (NOLOCK)

文章目录

  • [WITH (NOLOCK) 是什么?](#WITH (NOLOCK) 是什么?)
  • 代码示例

WITH (NOLOCK) 是什么?

WITH (NOLOCK) 也叫 未提交读(READ UNCOMMITTED),是 SQL Server 中的一种表提示(Table Hint),本质是让查询语句忽略目标表上的共享锁和排他锁,直接读取数据,核心目的是提升查询性能、避免查询被阻塞。

SQL Server 默认的隔离级别是 READ COMMITTED(已提交读),即查询会等待目标数据上的锁释放后再读取,且只能读取已提交的数据;而 NOLOCK 会强制查询使用 READ UNCOMMITTED 隔离级别,打破这个规则。

代码示例

java 复制代码
package com.qf.config;


import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
@Component
public class MybatisPlusSqlInterceptor implements Interceptor {


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        // 先判断是不是SELECT操作 不是直接跳过
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
            return invocation.proceed();
        }
        String id = mappedStatement.getId();
        String methodName = id.substring(id.lastIndexOf(".") + 1, id.length());
        //只有Mybatis plus的selectOne和selectList做特殊处理
        if (!methodName.equals("selectOne") && !methodName.equals("selectList") && !methodName.equals("selectMaps")) {
            return invocation.proceed();
        }
        BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
        // 执行的SQL语句
        String originalSql = boundSql.getSql().replace("\n", "");
        String tableName = extractFromClause(originalSql);
        log.info("要执行的sql:{}", originalSql);
        log.info("正则表达式获取要执行的sql的表名:{}", tableName);
        if (StringUtils.isNotEmpty(tableName)) {
            String finalSql = originalSql.replace(tableName, tableName + " WITH(NOLOCK)");
            log.info("处理后的sql:{}", finalSql);
            metaObject.setValue("delegate.boundSql.sql", finalSql);
        }
        return invocation.proceed();
    }

    public static String extractFromClause(String query) {
        String table = "";
        Pattern p = Pattern.compile("FROM \\[(.*?)\\]");
        Matcher m = p.matcher(query);
        if (m.find()) {
            table = m.group();
        }
        return table.trim();
    }
}

相关推荐
怣502 分钟前
MySQL多表连接:全外连接、交叉连接与结果集合并详解
数据库·sql
wjhx23 分钟前
QT中对蓝牙权限的申请,整理一下
java·数据库·qt
冰暮流星33 分钟前
javascript之二重循环练习
开发语言·javascript·数据库
万岳科技系统开发1 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
冉冰学姐1 小时前
SSM智慧社区管理系统jby69(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·管理系统·智慧社区·ssm 框架
杨超越luckly1 小时前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强
斯普信专业组1 小时前
构建基于MCP的MySQL智能运维平台:从开源服务端到交互式AI助手
运维·mysql·开源·mcp
Elastic 中国社区官方博客1 小时前
Elasticsearch:Workflows 介绍 - 9.3
大数据·数据库·人工智能·elasticsearch·ai·全文检索
仍然.2 小时前
MYSQL--- 聚合查询,分组查询和联合查询
数据库
一 乐2 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端