手写mybatis完整sql插件问题及实现思路

问题产生

我们在使用mybatis的过程中,如果开启了mysql的日志功能的话,会在控制台打印一些sql的信息,但是日志中的sql语句,是没有拼接参数的,也就是说,是不可以直接放到数据库中执行的。
some times,我们在调试问题的时候,会希望有一个直接可以运行的SQL语句,那将方便很多,特别是在sql语句绑定参数很多的时候。

现象描述

默认的mysql日志配置和打印情况如下:

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
==>  Preparing: select * from hwc_users a where a.name = ? and a.age = ?
==> Parameters: huwenchao(String), 35(Integer)
<==      Total: 0

解决思路

通过思考,我觉得可以通过mybatis的插件机制来解决这个问题。
首先,我们查看源码,发现mysql的PreparedStatement的toString方法中,直接通过asSql方法展示了完整的sql语句:

其次,mybatis中StatementHandler以及ParameterHandler接口中,都有相应的方法能够拦截到Statement:


具体实现

我们随机选择拦截ParameterHandler来进行完整sql语句的输出:

步骤一、编写拦截器类,并配置拦截的类和方法:

package com.huwc.interceptor;

import com.mysql.jdbc.JDBC42PreparedStatement;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.logging.jdbc.PreparedStatementLogger;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.sql.PreparedStatement;
import java.util.Properties;

@Intercepts({
    @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})
}
)
public class MybatisLogInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        PreparedStatement statement = (PreparedStatement) invocation.getArgs()[0];
        PreparedStatement statement1 = null ;
        if(Proxy.isProxyClass(statement.getClass())){
            InvocationHandler handler = Proxy.getInvocationHandler(statement);
            if(handler.getClass().getName().endsWith(".PreparedStatementLogger")){
                Field field = handler.getClass().getDeclaredField("statement");
                field.setAccessible(true);
                statement1 = (PreparedStatement) field.get(handler);
            }
        }

        System.out.println("================================= execute sql ==============================");
        System.out.println(statement1.toString());
        System.out.println("================================= execute sql ==============================");

        return invocation.proceed();

    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

步骤二、在mybatis配置文件中进行拦截器的注册:

 <plugins>
        <plugin interceptor="com.huwc.interceptor.MybatisLogInterceptor"></plugin>
    </plugins>

步骤三、测试结果:

==>  Preparing: select * from hwc_users a where a.name = ? and a.age = ?
================================= execute sql ==============================
com.mysql.jdbc.JDBC42PreparedStatement@53fb3dab: select * from hwc_users a where a.name = ** NOT SPECIFIED ** and a.age = ** NOT SPECIFIED **
================================= execute sql ==============================
==> Parameters: huwenchao(String), 35(Integer)

结果我们发现语句打印的有问题,绑定的参数没有打印出来。
仔细一看,发现我们拦截的就是ParameterHandler的绑定参数方法,且是在方法执行之前进行的打印,显然,参数还未绑定,所以我们调整一下拦截方法的执行过程:

重新执行,结果正常:

以上就是手写mybatis完整sql插件的详细内容,更多关于mybatis完整sql插件的资料请关注我们其它相关文章!

(0)

相关推荐

  • mybatis 插件: 打印 sql 及其执行时间实现方法

    Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用: Executor(update.query.flushStatements.commint.rollback.getTransaction.close.isClosed) ParameterHandler(getParameterObject.setParameters) ResultSetHandler(handleResult

  • idea插件之mybatis log plugin控制台sql的问题

    兄dei,耐心把我的写的看完,我写的不繁琐,很好理解. IDEA插件之Mybatis Log plugin 破解及安装方法 去Idea的plugins里面搜索mybatis log plugin.如果搜不到,没关系,这可能跟我们激活的idea时候填的激活码有关系,作者只是根据自身使用的idea经验怀疑是这个原因,不说这个 下面是官方的连接 https://plugins.jetbrains.com/plugin/10065-mybatis-log-plugin .来这里选个版本下载就行.下载完是

  • 解决mybatis-plus3.4.1分页插件PaginationInterceptor和防止全表更新与删除插件SqlExplainInterceptor过时失效问题

    前言 在Mybatis Plus 3.4.0版本之后PaginationInterceptor插件就失效,新增Mybatis Plus 3.4.0的新内置插件 提示:以下是本篇文章正文内容,下面案例可供参考 分页插件 一.之前的配置 在sqlSessionFactoryBean中配置插件 <property name="plugins"> <array> <bean class="com.baomidou.mybatisplus.extensio

  • Spring mvc整合mybatis(crud+分页插件)操作mysql

    一.web.xml配置 我们都知道java ee的项目启动的第一件事就是读取web.xml,spring mvc 的web.xml我在上一篇文章中也做了详细讲解,不懂的可以回头看看,讲解的这个项目源码我也会放到github上,也可以去那里看看,这里就不做介绍了. web.xml 配置 <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/c

  • 在IDEA中安装MyBatis Log Plugin插件,执行mybatis的sql语句(推荐)

    查看代码执行mybatis的sql语句 File–>Settings–>Plugins 搜索 MyBatis Log Plugin Installed安装之后重启,点击上方的Tools就能看到 然后debug执行代码之后 点击启动MyBatis Log Plugin插件 就可以查看每一步执行的sql 到此这篇关于在IDEA中安装MyBatis Log Plugin插件,执行mybatis的sql语句(推荐)的文章就介绍到这了,更多相关idea 安装MyBatis Log Plugin插件内容请

  • MyBatis Log 插件无法显示SQL语句的原因解析

    Mybatis有什么用 前两天跟阿里的大牛聊天,他讲到对于性能要求高,需求变化多的互联网项目来说,用在sql优化上的开发时间是大头,有时候代码写出来一小时,优化反反复复可能要几个星期,这时候Mybatis这种配置比较灵活的框架优势就显现了!Mybatis为什么在国内这么流行? 1. 什么是Mybatis? MyBatis是支持定制化sql.存储过程以及高级映射的优秀的持久层框架.MyBatis避免了几乎所有的JDBC代码和手工设置参数以及抽取结果集.MyBatis使用简单的XML或注解来配置和映

  • 手写mybatis完整sql插件问题及实现思路

    问题产生 我们在使用mybatis的过程中,如果开启了mysql的日志功能的话,会在控制台打印一些sql的信息,但是日志中的sql语句,是没有拼接参数的,也就是说,是不可以直接放到数据库中执行的. some times,我们在调试问题的时候,会希望有一个直接可以运行的SQL语句,那将方便很多,特别是在sql语句绑定参数很多的时候. 现象描述 默认的mysql日志配置和打印情况如下: <settings> <setting name="logImpl" value=&q

  • Mybatis分页插件PageHelper手写实现示例

    目录 引言 编写我们的插件类 上面有二个核心方法 获取记录总数 分页查询记录数 如何获取前端传递过来的参数? 总结 引言 PageHelper是一个非常好用的插件,以至于很想知道它底层是怎么实现的.至于MyBatis插件概念原理网上有很多,我不太喜欢去写一些概念性的东西,我比较喜欢自己动手实现的那种,话不多说,我们开干 搭建一个SpringBoot+MyBatis+MySql项目 编写我们的插件类 package com.example.demo.plugin; import org.apach

  • Mybatis打印替换占位符后的完整Sql教程

    利用mybtis插件打印完整的sql,将占位符?替换成实际值 import org.apache.ibatis.cache.CacheKey; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.Paramete

  • Angularjs 手写日历的实现代码(不用插件)

    本文介绍了Angularjs 手写日历的实现代码(不用插件),分享给大家,具体如下: 效果: Html: <div class="plan_content_box" data-ng-init="showTime()"> <div class="field" style="width: 100%;"> <span class="field_label" style="w

  • 基于vue手写tree插件的那点事儿

    前言 Tree树形控件在前端开发中必不可少,对于数据的展示现在网站大都采取树形展示.因为大数据全部展示出来对于用户来说是不友好的.今天我们自己手写一个Tree插件. iview提供的控件 iview已经很成熟了,如果说我写的控件和iview提供的控件谁更好,那肯定是选择iview , 手写控件只是为了更好的了解vue父子组件之间的通信的. 请读者还是不要拿我的控件和iview或者其他第三方的去对比.下面我们先来看看iview的Tree控件如何使用 <template> <Tree :da

  • 手写vite插件教程示例

    目录 前言 1. 什么是 vite 插件 2. 为什么要写 vite 插件 创建  vite 插件通用模板 1. 初始化 2. 配置 eslint 和 prettier(可选) 3. 新增 src/index.ts 入口 4. 创建 examples 目录 5. 配置 examples/vite-vue3 项目 6. 安装 tsup 配置运行命令 7. 开发环境运行 8. 发布 vite 的插件钩子 hooks 们 1. vite 独有的钩子 2. vite 与 rollup 的通用钩子之构建阶

  • TypeScript手写一个简单的eslint插件实例

    目录 引言 前置知识 第一个eslint规则:no-console 本地测试 本地查看效果 no-console规则添加功能:排除用户指定的文件 发布npm包 引言 看到参考链接1以后,觉得用TS写一个eslint插件应该很简单⌨️,尝试下来确实如此. 前置知识 本文假设 你对AST遍历有所了解. 你写过单测用例. 第一个eslint规则:no-console 为了简单,我们只使用tsc进行构建.首先package.json需要设置入口"main": "dist/index.

  • Pytorch实现的手写数字mnist识别功能完整示例

    本文实例讲述了Pytorch实现的手写数字mnist识别功能.分享给大家供大家参考,具体如下: import torch import torchvision as tv import torchvision.transforms as transforms import torch.nn as nn import torch.optim as optim import argparse # 定义是否使用GPU device = torch.device("cuda" if torch

  • Python使用gluon/mxnet模块实现的mnist手写数字识别功能完整示例

    本文实例讲述了Python使用gluon/mxnet模块实现的mnist手写数字识别功能.分享给大家供大家参考,具体如下: import gluonbook as gb from mxnet import autograd,nd,init,gluon from mxnet.gluon import loss as gloss,data as gdata,nn,utils as gutils import mxnet as mx net = nn.Sequential() with net.nam

随机推荐