当前位置: 首页 > news >正文

技术分享:MyBatis SQL 日志解析脚本

技术分享:MyBatis SQL 日志解析脚本

  • 1. 脚本功能概述
  • 2. 实现细节
    • 2.1 HTML 结构
    • 2.2 JavaScript 逻辑
  • 3. 脚本代码
  • 4. 使用方法
    • 4.1 示例
  • 5. 总结

在日常开发中,使用 MyBatis 作为持久层框架时,我们经常需要查看 SQL 日志以调试和优化查询。然而,MyBatis 的日志输出通常包含占位符和参数信息,这使得直接执行这些 SQL 语句变得困难。为了解决这个问题,我们开发了一个简单的 HTML 和 JavaScript 脚本,用于解析 MyBatis 的 SQL 日志并生成可执行的 SQL 语句。

1. 脚本功能概述

该脚本的主要功能是:

  1. 解析 SQL 日志:从 MyBatis 日志中提取 SQL 语句和参数。
  2. 参数替换:将 SQL 语句中的占位符 ? 替换为实际的参数值。
  3. 生成可执行 SQL:输出完整的 SQL 语句,便于在数据库中直接执行。

2. 实现细节

2.1 HTML 结构

脚本的 HTML 部分提供了一个简单的用户界面,包含输入区域、解析按钮和输出区域。

  • 输入区域:用户可以在此粘贴 MyBatis 的 SQL 日志。
  • 解析按钮:点击后触发 JavaScript 函数进行解析。
  • 输出区域:显示解析后的可执行 SQL 语句。

2.2 JavaScript 逻辑

JavaScript 部分实现了日志解析的核心逻辑:

  • 日志分割:通过换行符将日志分割为多行,逐行处理。
  • SQL 语句提取:识别包含 Preparing: 的行,提取 SQL 语句。
  • 参数解析:识别包含 Parameters: 的行,提取参数并根据类型进行处理。
    • 字符串和时间戳:用单引号包裹,处理转义字符。
    • 空值:替换为 NULL
    • 其他类型:直接替换。
  • 结果输出:将替换后的 SQL 语句显示在输出区域。

3. 脚本代码

创建一个.html文件,编辑,将脚本内容贴至文件内,保存,用浏览器打开文件即可使用

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Mybatis SQL日志解析</title>
    <script type="text/javascript">
        function f(obj) {
            try {
                var textVa = obj.value;
                var logs = textVa.split('\n'); // Split by newline
                var results = [];
                var currentStatement = null;

                logs.forEach(function(log) {
                    // Check if this line contains "Preparing:" or "Parameters:"
                    if (log.indexOf('Preparing:') !== -1) {
                        if (currentStatement !== null) {
                            // If we have a current statement, push it to the results
                            results.push(currentStatement);
                        }
                        // Start a new statement
                        currentStatement = log.substring(log.indexOf('Preparing:') + "Preparing:".length).trim();
                    } else if (log.indexOf('Parameters:') !== -1 && currentStatement !== null) {
                        // If we find parameters and have a current statement, parse the parameters
                        var parametersStr = log.substring(log.indexOf('Parameters:') + "Parameters:".length).trim();
                        var parameters = parametersStr.split(/,(?![^()]*\))/g); // Use regex to split correctly
                        for (var i = 0; i < parameters.length; i++) {
                            var paramValue = parameters[i].trim();
                            if (paramValue === "null") {
                                currentStatement = currentStatement.replace("?", "NULL");
                            } else {
                                var typeStr = paramValue.substring(paramValue.indexOf("(") + 1, paramValue.indexOf(")"));
                                paramValue = paramValue.substring(0, paramValue.indexOf("(")).trim();
                                if (typeStr === "String" || typeStr === "Timestamp") {
                                    paramValue = "'" + paramValue.replace("'", "''") + "'";
                                }
                                currentStatement = currentStatement.replace("?", paramValue);
                            }
                        }
                        // Add the final statement to the results and reset currentStatement
                        results.push(currentStatement);
                        currentStatement = null;
                    }
                });

                // If there's a remaining statement, push it to the results
                if (currentStatement !== null) {
                    results.push(currentStatement);
                }

                document.getElementById("d1").value = results.join("\n\n");
            } catch (e) {
                console.error(e);
                alert("解析SQL时发生错误:" + e.message);
            }
        }
        function copySQL() {
            var SQL = document.getElementById("d1");
            navigator.clipboard.writeText(SQL.value).then(function() {
                var msg = document.getElementById("msg");
                msg.innerHTML = "已复制到剪切板";
                setTimeout(function () {
                    msg.innerHTML = "";
                }, 3000);
            }).catch(function(err) {
                console.error("复制失败:", err);
                alert("复制SQL时发生错误:" + err.message);
            });
        }
        function clearLog(obj) {
            obj.value = "";
        }
    </script>
</head>
<body>

<h2><font color="#00bfff"> 输入Mybatis SQL日志:</font></h2>
<textarea id="sqlLog" rows="12" cols="140" style="font-size:12px;font-family: 'CourierNew';font-weight: bold;width: 98%;"></textarea>
<div style="border:0px deepskyblue solid;width:1425px;height:50px;text-align:right;">
    <button style="color:mediumblue;width:100px;height:60px" type="button" onclick="clearLog(document.getElementById('sqlLog'))">清空</button>
    <button style="color:mediumblue;width:100px;height:60px" type="submit" onclick="f(document.getElementById('sqlLog'))">解析SQL</button>
</div>

<h2><font color="#32cd32">解析为可执行SQL:</font></h2>
<textarea id="d1" rows="12" cols="140" style="font-size:12px;font-family: 'CourierNew';font-weight: bold;width: 98%;"></textarea>
<div style="border:0px deepskyblue solid;width:1425px;height:50px;text-align:right;">
    <button style="color:mediumblue;width:100px;height:60px" type="button" onclick="copySQL()">复制SQL</button>
</div>

<div id="msg" style="color:cornflowerblue;border:0px black solid;width:800px;height:20px;text-align:right;font-style: initial;font-size: large"></div>

</body>
</html>


4. 使用方法

  1. 将 MyBatis 的 SQL 日志粘贴到输入区域。
  2. 点击"解析SQL"按钮。
  3. 在输出区域查看并复制解析后的 SQL 语句。

4.1 示例

假设输入的日志为:

Preparing: INSERT INTO users (name, email) VALUES (?, ?)
Parameters: John(String), null

解析后的输出为:

INSERT INTO users (name, email) VALUES ('John', NULL)

在这里插入图片描述

5. 总结

通过这个简单的脚本,我们可以快速将 MyBatis 的 SQL 日志转换为可执行的 SQL 语句,极大地方便了开发和调试工作。希望这个工具能对你有所帮助!

相关文章:

  • 第二章:16.5 决策树处理连续值特征
  • RLHF的改进算法DPO原理
  • Ubuntu安装Redis
  • 使用 Python 和 OpenCV 进行图像边缘检测:从基础到实战
  • idea-代码补全快捷键
  • 科普:“拉取镜像”和“下载安装”
  • 大厂算法面试常见问题总结:高频考点与备战指南
  • Kubernetes的Ingress和Service有什么区别?
  • Golang GORM系列:GORM无缝集成web框架
  • 基于Matlab实现永磁同步电机矢量控制仿真程序
  • 【JavaEE进阶】MyBatis通过注解实现增删改查
  • AStar低代码平台RpcServiceBase的应用:客户端事务管理
  • Git Stash 使用与应用场景介绍(中英双语)
  • 网页制作04-html,css,javascript初认识のhtml如何使用列表
  • 【LeetCode: LCR 126. 斐波那契数 + 动态规划】
  • 内核数据结构用法(2)list
  • 开源模型应用落地-qwen2-7b-instruct-LoRA微调模型合并-LLaMA-Factory-单机多卡-RTX 4090双卡(六)
  • halcon激光三角测量(二十三)inspect_3d_surface_intersections
  • Laravel从入门到上云
  • Deepseek整合SpringAI
  • “拼好假”的年轻人,今年有哪些旅游新玩法?
  • 雷军:过去一个多月是创办小米以来最艰难的时间
  • 习近平会见古巴国家主席迪亚斯-卡内尔
  • 国办印发《关于进一步加强困境儿童福利保障工作的意见》
  • 新村回响:一周城市生活
  • 浙江一民企拍地后遭政府两次违约,“民告官”三年又提起民事诉讼