您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Mybatis攔截器打印sql問題怎么解決”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
關(guān)閉log4j2打印mybatis的sql配置,如果本來就沒開啟,那不需要。
在springboot的yml文件配置變量logging.sql.enable=true,對攔截器做開關(guān)控制。
// 采用自定義攔截器打印sql日志 sessionFactory.setPlugins(new Interceptor[]{this.getSqlLogInterceptor()});
@Value("${logging.sql.enable:true}") private Boolean sqlEnable;
Object target = invocation.getTarget(); StatementHandler statementHandler = (StatementHandler) target; //獲取綁定的SQL對象 BoundSql boundSql = statementHandler.getBoundSql(); //得到需要執(zhí)行的sql語句,并進(jìn)行格式 String sql = boundSql.getSql();
//需要綁定的參數(shù)映射對象 List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();
public String buidSql(String sql,Object[] parameters) { if (parameters == null || sql == null) { return ""; } List<Object> parametersArray = Arrays.asList(parameters); List<Object> list = new ArrayList<Object>(parametersArray); while (sql.indexOf("?") != -1 && list.size() > 0 && parameters.length > 0) { Object obj = list.get(0); if(null!=obj && obj instanceof String){ sql = sql.replaceFirst("\\?", "'"+obj.toString()+"'"); }else if(null!=obj){ sql = sql.replaceFirst("\\?", obj.toString()); } list.remove(0); } return sql.replaceAll("(\r?\n(\\s*\r?\n)+)", "\r\n"); }
log.debug(String.format( "\n########################### Sql Start ###########################" + "\n StartTime : %s" + "\n ExecuteID : %s" + "\n ExecuteSQL : %s" + "\n ExecuteTime : %s ms" + "\n########################### Sql End ###########################\n" ,startTimeStr,executeID,this.buidSql(sql,args.toString().split(",")),exeTime));
攔截器完整代碼
package com.cloudpaas.plugin.mybatis.interceptor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.mapping.ParameterMode; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.apache.ibatis.scripting.defaults.DefaultParameterHandler; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.type.TypeHandlerRegistry; import org.springframework.beans.factory.annotation.Value; import java.lang.reflect.Field; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.*; @Intercepts({ @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}), @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}), @Signature(type = StatementHandler.class, method = "batch", args = { Statement.class }) }) @Slf4j public class SqlLogInterceptor implements Interceptor { private SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Value("${logging.sql.enable:true}") private Boolean sqlEnable; @Override public Object intercept(Invocation invocation) throws Throwable { if(!sqlEnable){ return invocation.proceed(); } Object target = invocation.getTarget(); MetaObject mObject = SystemMetaObject.forObject(invocation.getTarget()); MappedStatement mappedStatement = (MappedStatement)mObject.getValue("delegate.mappedStatement"); // 執(zhí)行的mapper statement ID String executeID = mappedStatement.getId(); //獲取當(dāng)前的開始時間戳 long startTime = System.currentTimeMillis(); //記錄當(dāng)前時間 String startTimeStr=sdf.format(new Date()); StatementHandler statementHandler = (StatementHandler) target; try { return invocation.proceed(); } finally { long endTime = System.currentTimeMillis(); //sql的執(zhí)行的時間 long exeTime = endTime - startTime; try{ //獲取綁定的SQL對象 BoundSql boundSql = statementHandler.getBoundSql(); //得到需要執(zhí)行的sql語句,并進(jìn)行格式 String sql = boundSql.getSql(); sql=formatSql(sql); //得到默認(rèn)的參數(shù)處理器 DefaultParameterHandler dph=(DefaultParameterHandler)statementHandler.getParameterHandler(); //利用反射機(jī)制,從DefaultParameterHandler獲取Configuration和TypeHandlerRegistry Field configurationField=dph.getClass().getDeclaredField("configuration"); Field typeHandlerRegistryField=dph.getClass().getDeclaredField("typeHandlerRegistry"); //設(shè)置私有屬性可訪問 configurationField.setAccessible(true); //設(shè)置私有屬性可訪問 typeHandlerRegistryField.setAccessible(true); Configuration configuration=(Configuration) configurationField.get(dph); TypeHandlerRegistry typeHandlerRegistry=(TypeHandlerRegistry) typeHandlerRegistryField.get(dph); //sql的參數(shù)對象 Object parameterObject = boundSql.getParameterObject(); //需要綁定的參數(shù)映射對象 List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings(); //處理sql的參數(shù),該部分參考的是DefaultParameterHandler中setParameters方法中的實(shí)現(xiàn) StringBuffer args=new StringBuffer(); if(parameterMappingList!=null && parameterMappingList.size()>0){ for(ParameterMapping parameterMapping:parameterMappingList){ //如果該參數(shù)不是輸出參數(shù),則進(jìn)行處理 if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; //參數(shù)的名字,屬性 String propertyName = parameterMapping.getProperty(); //先從附加的,主要是list、array等的處理 if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { //typeHandlerRegistry注冊了某個類的處理 value = parameterObject; } else { //默認(rèn)的MetaObject 的處理,根據(jù)參數(shù)獲取值 MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } if(value!=null){ if(value instanceof Date){ //如果是日期,則格式化一下 value=sdf.format(value); } } args.append(",").append(value); } } //刪除第一個逗號 args.deleteCharAt(0); } log.debug(String.format( "\n########################### Sql Start ###########################" + "\n StartTime : %s" + "\n ExecuteID : %s" + "\n ExecuteSQL : %s" + "\n ExecuteTime : %s ms" + "\n########################### Sql End ###########################\n" ,startTimeStr,executeID,this.buidSql(sql,args.toString().split(",")),exeTime)); }catch(Exception e){ } } } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } private String formatSql(String sql) { // 輸入sql字符串空判斷 if (sql == null || sql.length() == 0) { return ""; } //格式sql 將回車換行制表符等替換成空,在將連續(xù)多個空格替換成1個空格,然后在去掉左右括號兩邊的空格,在去掉逗號左右兩個的空格 return sql.replaceAll("[\\t\\n\\x0B\\f\\r]", "").replaceAll(" +", " ") .replaceAll(" *\\( *", "(").replaceAll(" *\\) *", ")").replaceAll(" *, *", ","); } public String buidSql(String sql,Object[] parameters) { if (parameters == null || sql == null) { return ""; } List<Object> parametersArray = Arrays.asList(parameters); List<Object> list = new ArrayList<Object>(parametersArray); while (sql.indexOf("?") != -1 && list.size() > 0 && parameters.length > 0) { Object obj = list.get(0); if(null!=obj && obj instanceof String){ sql = sql.replaceFirst("\\?", "'"+obj.toString()+"'"); }else if(null!=obj){ sql = sql.replaceFirst("\\?", obj.toString()); } list.remove(0); } return sql.replaceAll("(\r?\n(\\s*\r?\n)+)", "\r\n"); } }
“Mybatis攔截器打印sql問題怎么解決”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。