如何優雅的將Mybatis日誌中的Preparing與Parameters轉換為可執行SQL
原文連結
疫情期間大家宅在家裡是不是已經快憋出“病”了~~
公司給開了VPN,手機電腦都能連,手機裝上APP測試包,就能幹活了,所以walking從2020.02.01入京以來,已經窩在家裡11天了。這兩天在家遠端辦公,預測下週也要在家辦公。。
最近在家隔離期間,其實也是學的少玩的多。這不,今天在看Mybatis原始碼的時候發現了一款好用的Mybatis外掛和一個轉換工具,今天就趕忙寫出來分享給大夥。
我們大家在工作中應該都是用過Mybatis吧,有時候我們在本地除錯的時候,會開啟Mybatis的SQL日誌列印,那麼打印出來的SQL是下圖這樣的
你可以看到預編譯的SQL條件用佔位符(?)了select * from User where id = ? ,並不是真實的SQL select * 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的時候用。
原作者的文章地址:https://blog.csdn.net/Zale_J/article/details/89402668
只需要搞個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; } </script> </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也沒說,應該是做了一些優化什麼的吧。具體什麼我也沒有驗證。
優化的原文:https://www.cnblogs.com/n031/p/11176346.html
下面是效果圖:
優化的程式碼:
<!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>
這倆種方式具體用哪個視情況而定。感謝這兩位作者的聰明才智和無私奉獻。
如果感覺有用的話趕緊分享給你的小夥伴吧,現在沒時間搞的話先收藏起來吧~
武漢加油!中國加油!!
手機閱讀的使用者可移至公眾號哦,更方便。