Mybatis Sql Log在线美化工具

236 阅读2分钟

上干货

服务器打印的Mybatis sql日志,如

2025-04-17 15:04:51.736 DEBUG 1 --- [io-9002-exec-10] c.t.s.m.S.selectSysUserOfficeList : ==> Preparing: select user_id, company_id, office_id, post_id, organization_type, o.name as officeName, o.short_name as officeShortName, c.logo, c.name as companyName, c.short_name as companyShortName from sys_user_office a left join sys_office c on a.company_id = c.id left join sys_office o on a.office_id = o.id WHERE user_id = ? and organization_type = ?

2025-04-17 15:04:51.736 DEBUG 1 --- [io-9002-exec-10] c.t.s.m.S.selectSysUserOfficeList : ==> Parameters: 196a0f347f0647a89b9d53b8551c1c87(String), slave(String)

通过工具把sql日志直接转换为可执行sql,现在搞了个工具,有兴趣的直接在线使用

使用截图

image.png

image.png

源码(直接本地下载为.html打开就行了)

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mybatis SQL 解析器</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/sql-formatter/4.0.2/sql-formatter.min.js"></script>
    <script type="text/javascript">
        function f(obj) {
            var textVa = obj.value;
            // 获取带问号的 SQL 语句
            var statementStartIndex = textVa.indexOf('Preparing: ');
            if (statementStartIndex === -1) {
                alert('未找到 SQL 语句,请检查输入!');
                return;
            }
            var statementEndIndex = textVa.indexOf('\n', statementStartIndex);
            if (statementEndIndex === -1) {
                statementEndIndex = textVa.length;
            }
            var statementStr = textVa.substring(statementStartIndex + "Preparing: ".length, statementEndIndex);

            // 获取参数
            var parametersStartIndex = textVa.indexOf('Parameters: ');
            if (parametersStartIndex === -1) {
                alert('未找到参数,请检查输入!');
                return;
            }
            var parametersEndIndex = textVa.indexOf('\n', parametersStartIndex);
            if (parametersEndIndex === -1) {
                parametersEndIndex = textVa.length;
            }
            var parametersStr = textVa.substring(parametersStartIndex + "Parameters: ".length, parametersEndIndex);
            var paramItems = parametersStr.split(',');
            var parameters = [];
            for (var i = 0; i < paramItems.length; i++) {
                var paramMatch = paramItems[i].match(/^\s*(.*?)\((.*?)\)$/);
                if (paramMatch) {
                    parameters.push({
                        value: paramMatch[1].trim(),
                        type: paramMatch[2].trim()
                    });
                }
            }

            // 替换占位符
            var placeholders = statementStr.match(/\?/g);
            if (placeholders && placeholders.length!== parameters.length) {
                alert('参数数量与占位符数量不匹配,请检查输入!');
                return;
            }
            for (var i = 0; i < parameters.length; i++) {
                var param = parameters[i];
                if (param.type === "String" || param.type === "Timestamp") {
                    statementStr = statementStr.replace("?", `'${param.value}'`);
                } else {
                    statementStr = statementStr.replace("?", param.value);
                }
            }

            // 美化 SQL
            var formattedSQL = sqlFormatter.format(statementStr);
            document.getElementById("d1").value = formattedSQL;
            document.getElementById("d1").dataset.compressed = "false";
            document.getElementById("toggleSQL").innerHTML = '<i class="fa-solid fa-compress"></i> 压缩 SQL';
            return textVa;
        }

        async function copySQL() {
            var SQL = document.getElementById("d1").value;
            try {
                await navigator.clipboard.writeText(SQL);
                var msg = document.getElementById("msg");
                msg.innerHTML = "已复制到剪切板";
                setTimeout(() => {
                    msg.innerHTML = "";
                }, 3000);
            } catch (err) {
                alert('复制失败,请手动复制!');
            }
        }

        function clearLog(obj) {
            obj.value = "";
        }

        function toggleSQL() {
            var sqlTextarea = document.getElementById("d1");
            var isCompressed = sqlTextarea.dataset.compressed === "true";
            if (isCompressed) {
                var originalSQL = sqlTextarea.dataset.originalSql;
                sqlTextarea.value = originalSQL;
                sqlTextarea.dataset.compressed = "false";
                document.getElementById("toggleSQL").innerHTML = '<i class="fa-solid fa-compress"></i> 压缩 SQL';
            } else {
                var originalSQL = sqlTextarea.value;
                var compressedSQL = originalSQL.replace(/\s+/g, " ").trim();
                sqlTextarea.dataset.originalSql = originalSQL;
                sqlTextarea.value = compressedSQL;
                sqlTextarea.dataset.compressed = "true";
                document.getElementById("toggleSQL").innerHTML = '<i class="fa-solid fa-expand"></i> 展开 SQL';
            }
        }
    </script>
</head>

<body class="bg-gray-100 font-sans">
    <div class="container mx-auto p-4 flex flex-col md:flex-row">
        <div class="w-full md:w-1/2 p-4">
            <h2 class="text-2xl text-blue-600 mb-4">输入 Mybatis SQL 日志:</h2>
            <textarea id="sqlLog" rows="13" cols="140"
                class="w-full p-3 border border-gray-300 rounded-md mb-4 text-lg focus:ring-blue-500 focus:border-blue-500"></textarea>
            <div class="flex justify-end space-x-4 mb-8">
                <button onclick="clearLog(document.getElementById('sqlLog'))"
                    class="bg-blue-500 hover:bg-blue-600 text-white py-3 px-6 rounded-md transition duration-300">
                    清空
                </button>
                <button onclick="f(document.getElementById('sqlLog'))"
                    class="bg-blue-500 hover:bg-blue-600 text-white py-3 px-6 rounded-md transition duration-300">
                    解析 SQL
                </button>
            </div>
        </div>
        <div class="w-full md:w-1/2 p-4">
            <h2 class="text-2xl text-green-600 mb-4">解析为可执行 SQL:</h2>
            <textarea id="d1" rows="13" cols="140"
                class="w-full p-3 border border-gray-300 rounded-md mb-4 text-lg focus:ring-blue-500 focus:border-blue-500"></textarea>
            <div class="flex justify-end space-x-4 mb-4">
                <button onclick="toggleSQL()" id="toggleSQL"
                    class="bg-blue-500 hover:bg-blue-600 text-white py-3 px-6 rounded-md transition duration-300">
                    <i class="fa-solid fa-compress"></i> 压缩 SQL
                </button>
                <button onclick="copySQL()"
                    class="bg-blue-500 hover:bg-blue-600 text-white py-3 px-6 rounded-md transition duration-300">
                    复制 SQL
                </button>
            </div>
            <div id="msg" class="text-blue-500 text-right text-lg"></div>
        </div>
    </div>
</body>

</html>