上干货
服务器打印的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,现在搞了个工具,有兴趣的直接在线使用
使用截图
源码(直接本地下载为.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>