- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- 手寫(xiě)mybatis完整sql插件問(wèn)題及實(shí)現思路
我們在使用mybatis的過(guò)程中,如果開(kāi)啟了mysql的日志功能的話(huà),會(huì )在控制臺打印一些sql的信息,但是日志中的sql語(yǔ)句,是沒(méi)有拼接參數的,也就是說(shuō),是不可以直接放到數據庫中執行的。
some times,我們在調試問(wèn)題的時(shí)候,會(huì )希望有一個(gè)直接可以運行的SQL語(yǔ)句,那將方便很多,特別是在sql語(yǔ)句綁定參數很多的時(shí)候。
默認的mysql日志配置和打印情況如下:
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
==> Preparing: select * from hwc_users a where a.name = ? and a.age = ? ==> Parameters: huwenchao(String), 35(Integer) <== Total: 0
通過(guò)思考,我覺(jué)得可以通過(guò)mybatis的插件機制來(lái)解決這個(gè)問(wèn)題。
首先,我們查看源碼,發(fā)現mysql的PreparedStatement的toString方法中,直接通過(guò)asSql方法展示了完整的sql語(yǔ)句:
其次,mybatis中StatementHandler以及ParameterHandler接口中,都有相應的方法能夠攔截到Statement:
我們隨機選擇攔截ParameterHandler來(lái)進(jìn)行完整sql語(yǔ)句的輸出:
步驟一、編寫(xiě)攔截器類(lèi),并配置攔截的類(lèi)和方法:
package com.huwc.interceptor; import com.mysql.jdbc.JDBC42PreparedStatement; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.logging.jdbc.PreparedStatementLogger; import org.apache.ibatis.plugin.*; import org.apache.ibatis.scripting.defaults.DefaultParameterHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.sql.PreparedStatement; import java.util.Properties; @Intercepts({ @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}) } ) public class MybatisLogInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { PreparedStatement statement = (PreparedStatement) invocation.getArgs()[0]; PreparedStatement statement1 = null ; if(Proxy.isProxyClass(statement.getClass())){ InvocationHandler handler = Proxy.getInvocationHandler(statement); if(handler.getClass().getName().endsWith(".PreparedStatementLogger")){ Field field = handler.getClass().getDeclaredField("statement"); field.setAccessible(true); statement1 = (PreparedStatement) field.get(handler); } } System.out.println("================================= execute sql =============================="); System.out.println(statement1.toString()); System.out.println("================================= execute sql =============================="); return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } }
步驟二、在mybatis配置文件中進(jìn)行攔截器的注冊:
<plugins> <plugin interceptor="com.huwc.interceptor.MybatisLogInterceptor"></plugin> </plugins>
步驟三、測試結果:
==> Preparing: select * from hwc_users a where a.name = ? and a.age = ?
================================= execute sql ==============================
: select * from hwc_users a where a.name = ** NOT SPECIFIED ** and a.age = ** NOT SPECIFIED **
================================= execute sql ==============================
==> Parameters: huwenchao(String), 35(Integer)
結果我們發(fā)現語(yǔ)句打印的有問(wèn)題,綁定的參數沒(méi)有打印出來(lái)。
仔細一看,發(fā)現我們攔截的就是ParameterHandler的綁定參數方法,且是在方法執行之前進(jìn)行的打印,顯然,參數還未綁定,所以我們調整一下攔截方法的執行過(guò)程:
重新執行,結果正常:
以上就是手寫(xiě)mybatis完整sql插件的詳細內容,更多關(guān)于mybatis完整sql插件的資料請關(guān)注腳本之家其它相關(guān)文章!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站