现在的位置: 首页 > 数据库 > 正文

如何将Mybatis日志中的Preparing与Parameters转换为可执行SQL

2020年02月12日 数据库 ⁄ 共 4314字 ⁄ 字号 评论关闭

  今天在看Mybatis源码的时候发现了一款好用的Mybatis插件和一个转换工具,今天就赶忙写出来分享给大伙。


  我们大家在工作中应该都是用过Mybatis吧,有时候我们在本地调试的时候,会打开Mybatis的SQL日志打印。


  你可以看到预编译的SQL条件用占位符(?)了 select * from User where id = ? ,并不是真实的SQL selec t * from User where id = 1 。


  如果我们想得到真实的SQL,像那样参数少的话还可以自己把参数值手动拼上去,但是如果参数多了呢?是不是自己手动填就很麻烦了。


  不用MAME麻烦,今天就告诉你如何将mybatis日志的Preparing与Parameters转化为可执行sql。


  分享两种方式哈,一种是IDEA的插件mybatis log plugin,另一种是没有条件安装这个插件或者没有IDEA的时候,一种静态页面的方式。


  第一种 mybatis log plugin插件


  在Idea的setting - plugins里搜索mybatis log plugin,点击install即可,然后按照提示重启idea就行了。(如下已经安装完成)


  然后我们就可以选中SQL日志右键选择:Restore Sql from Selection


  然后就可以在Mybatis Log窗口看到真实的SQL了


  然后就可以复制出来到别的地方执行了。


  第二种 静态页面工具


  另外还有聪明的同学搞了个静态页面出来,以便于在无法安装上述plugin的时候用。


  只需要搞个html文件,然后把作者的源码贴进去,然后保存,用浏览器打开,再把mybatis日志帖进去点击“转换”即可得到真实SQL。源码我在下面也贴出来了。


  源代码:


  < !DOCTYPE html>


  < html>


  < head>


  < meta charset="utf-8">


  < title>< /title>


  < script type="text/javascript">


  function f(obj){


  var textVa = obj.value;


  // 获取带问号的SQL语句


  var statementStartIndex = textVa.indexOf('Preparing: ');


  var statementEndIndex = textVa.length-1;


  for(var i = statementStartIndex; i < textVa.length; i++) {


  if(textVa[i] == "\n") {


  statementEndIndex = i;


  break;


  }


  }


  var statementStr = textVa.substring(statementStartIndex+"Preparing: ".length, statementEndIndex);


  console.log(statementStr);


  //获取参数


  var parametersStartIndex = textVa.indexOf('Parameters: ');


  var parametersEndIndex = textVa.length-1;


  for(var i = parametersStartIndex; i < textVa.length; i++) {


  if(textVa[i] == "\n") {


  parametersEndIndex = i;


  break;


  } else {


  console.log(textVa[i]);


  }


  }


  var parametersStr = textVa.substring(parametersStartIndex+"Parameters: ".length, parametersEndIndex);


  parametersStr = parametersStr.split(",");


  console.log(parametersStr);


  for(var i = 0; i < parametersStr.length; i++) {


  // 如果数据中带括号将使用其他逻辑


  tempStr = parametersStr[i].substring(0, parametersStr[i].indexOf("("));


  // 获取括号中内容


  typeStr = parametersStr[i].substring(parametersStr[i].indexOf("(")+1,parametersStr[i].indexOf(")"));


  // 如果为字符类型


  if (typeStr == "String" || typeStr == "Timestamp") {


  statementStr = statementStr.replace("?", "'"+tempStr.trim()+"'");


  }else{


  // 数值类型


  statementStr = statementStr.replace("?", tempStr.trim());


  }


  }


  console.log(statementStr);


  document.getElementById("d1").innerHTML = statementStr;


  return textVa;


  }


  < /head>


  < body>


  < textarea name="getStr" id="1" rows="4" cols="100">< /textarea>


  < button type="submit" onclick="f(document.getElementById('1'))">转换< /button>


  < div id="d1">< /div>


  < /body>


  < /html>


  还有另外一位网友,说原作者的有一点bug,具体什么bug也没说,应该是做了一些优化什么的吧。具体什么我也没有验证。


  优化的代码:


  < !DOCTYPE html>


  < html>


  < head>


  < meta charset="utf-8">


  < title>mybatis转换< /title>


  < script type="text/javascript">


  function f(obj) {


  var textVa = obj.value;


  // 获取带问号的SQL语句


  var statementStartIndex = textVa.indexOf('Preparing: ');


  var statementEndIndex = textVa.length - 1;


  for (var i = statementStartIndex; i < textVa.length; i++) {


  if (textVa[i] == "\n") {


  statementEndIndex = i;


  break;


  }


  }


  var statementStr = textVa.substring(statementStartIndex + "Preparing: ".length, statementEndIndex);


  console.log(statementStr);


  //获取参数


  var parametersStartIndex = textVa.indexOf('Parameters: ');


  var parametersEndIndex = textVa.length;


  for (var i = parametersStartIndex; i < textVa.length; i++) {


  if (textVa[i] == "\n") {


  parametersEndIndex = i;


  break;


  } else {


  // console.log(textVa[i]);


  }


  }


  var parametersStr = textVa.substring(parametersStartIndex + "Parameters: ".length, parametersEndIndex);


  console.log(parametersStr);


  // 参数列表


  var parametersStrArr = parametersStr.split(",");


  console.log(parametersStrArr);


  for (var i = 0; i < parametersStrArr.length; i++) {


  tempStr = parametersStrArr[i].substring(0, parametersStrArr[i].indexOf("("));


  // 不含"("是null


  if(tempStr == ''){


  tempStr = "null";


  }


  // 如果数据中带括号需要判断参数类型


  typeStr = parametersStrArr[i].substring(parametersStrArr[i].indexOf("(") + 1, parametersStrArr[i].indexOf(")"));


  if (typeStr == "String" || typeStr == "Timestamp") {


  statementStr = statementStr.replace("?", "'" + tempStr.trim() + "'");


  } else {


  statementStr = statementStr.replace("?", tempStr.trim());


  }


  }


  console.log(statementStr);


  document.getElementById("d1").innerHTML = statementStr;


  return true;


  }


  < /script>


  < /head>


  < body>


  < button type="submit" onclick="f(document.getElementById('1'))">转换< /button>< br>< br>


  < textarea style="border:blue solid 2px;" name="getStr" id="1" rows="25" cols="150">< /textarea>< br>


  < p style="color:red;font:30px bold;">你的SQL< /p>


  < div style="border:red solid 2px;" id="d1">< /div>


  < /body>


  < /html>


  这俩种方式具体用哪个视情况而定。感谢这两位作者的聪明才智和无私奉献。

抱歉!评论已关闭.