IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Mybatis 输出SQL预编译后的语句及输出可执行的SQL语句 -> 正文阅读

[大数据]Mybatis 输出SQL预编译后的语句及输出可执行的SQL语句

环境

Mybatis、Druid(DataSource)

原因

业务需要及想进一步了解Mybatis知识。
下面就只写怎么做了,原理就一步一步去debug吧,自己动手能了解更多。

输出SQL预编译语句

共有两个方式能获取预编译后的语句:Mybatis拦截器、druid过滤器

Mybatis拦截器

@Slf4j
@Intercepts({
    @Signature(type = Executor.class, method = "query",
    args = {MappedStatement.class, Object.class,
            RowBounds.class, ResultHandler.class,
            TypeHandlerRegistry.class, Configuration.class})
})
public class SqlOutputInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // invocation.getArgs() 的值是 @Signature 注解里面的 args 列表
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object[] parameterObject = (Object[]) invocation.getArgs()[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
        Configuration configuration = (Configuration) invocation.getArgs()[6];
        // 获取未处理的 SQL 字符串
        String sql = boundSql.getSql();
        // 若想看真正执行的SQL语句,详情请看 DefaultParameterHandler.java 的 setParameters(PreparedStatement ps)
        // 输出与编译后的语句,带 “?” 的不可执行语句那种
        log.info(sql);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}

注意的两个点:
1、BoundSql 存储了预编译后的 sql,是带 “?” 的不可直接执行的sql。
2、可执行的sql语句其实在mybatis发送往数据库前就已经拼好了,但数据是以 byte[] 方式存储的,且 Encoding 是 “utf-8” 存储的。原理上,可以先获取这个 byte[] 以及 Encoding。然后 new String(byte[], Encoding) 的方式直接获取可执行的 sql。

Druid(DataSource) 过滤器

@Slf4j
public class SqlOutputFilter extends FilterEventAdapter {
    @Override
    public void init(DataSourceProxy dataSource) {
        super.init(dataSource);
        log.info("初始化SqlOutputFilter。");
    }
    @Override
    protected void statementExecuteAfter(StatementProxy statement, String sql, boolean result) {
        super.statementExecuteAfter(statement, sql, result);
        log.info("自定义过滤器,在执行操作后执行该方法,输出SQL={}", sql);
        int parametersSize = statement.getParametersSize();
        String formattedSql = sql;
        if (parametersSize > 0) {
            List<Object> parameters = new ArrayList<>(parametersSize);
            for (int i = 0; i < parametersSize; i++) {
                JdbcParameter parameter = statement.getParameter(i);
                parameters.add(parameter != null ? parameter.getValue() : null);
            }
            String dbType = statement.getConnectionProxy().getDirectDataSource().getDbType();
            formattedSql = SQLUtils.format(sql, dbType, parameters);
        }
        log.info("执行SQL语句,SQL={}", formattedSql);
    }
}

这个是参考了 Druid 的 LogFilter ,直接调用SQLUtils.format(String sql, String dbType, List parameters) 来获取可执行的 sql 语句。

执行顺序

拦截器跟过滤器都是递归方式执行:
正向:Mybatis 拦截器 -> Druid 过滤器
反向:Druid 过滤器 -> Mybatis 拦截器

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:36:15  更:2022-03-10 22:38:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:32:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码