中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mybatis 通過攔截器實現打印完整的sql語句并執行結果

發布時間:2020-10-28 17:51:49 來源:億速云 閱讀:1535 作者:Leah 欄目:開發技術

本篇文章為大家展示了mybatis 通過攔截器實現打印完整的sql語句并執行結果,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

開發過程中,如果使用mybatis做為ORM框架,經常需要打印出完整的sql語句以及執行的結果做為參考。

雖然mybatis結合日志框架可以做到,但打印出來的通常都是sql和參數分開的。

有時我們需要調試這條sql的時候,就需要把參數填進去,這樣未免有些浪費時間。

此時我們可以通過實現mybatis攔截器來做到打印帶參數的完整的sql,以及結果通過json輸出到控制臺。

直接看代碼和使用方法吧:

MyBatis攔截器打印不帶問號的完整sql語句攔截器

import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;
 
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry; 
 
/**
 * MyBatis攔截器打印不帶問號的完整sql語句
 * 
 * @author gogym
 * @version 2018年8月13日
 * @see MybatisInterceptor
 * @since
 */
@Intercepts({
 @Signature(type = Executor.class, method = "update", args = {MappedStatement.class,
  Object.class}),
 @Signature(type = Executor.class, method = "query", args = {MappedStatement.class,
  Object.class, RowBounds.class, ResultHandler.class})})
@SuppressWarnings({"unchecked", "rawtypes"})
public class MybatisInterceptor implements Interceptor
{
 @Override
 public Object intercept(Invocation invocation)
  throws Throwable
 {
  try
  {
   // 獲取xml中的一個select/update/insert/delete節點,是一條SQL語句
   MappedStatement mappedStatement = (MappedStatement)invocation.getArgs()[0];
   Object parameter = null;
   // 獲取參數,if語句成立,表示sql語句有參數,參數格式是map形式
   if (invocation.getArgs().length > 1)
   {
    parameter = invocation.getArgs()[1];
    System.out.println("parameter = " + parameter);
   }
   String sqlId = mappedStatement.getId(); // 獲取到節點的id,即sql語句的id
   System.out.println("sqlId = " + sqlId);
   BoundSql boundSql = mappedStatement.getBoundSql(parameter); // BoundSql就是封裝myBatis最終產生的sql類
   Configuration configuration = mappedStatement.getConfiguration(); // 獲取節點的配置
   String sql = getSql(configuration, boundSql, sqlId); // 獲取到最終的sql語句
   System.out.println("sql = " + sql);
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }
  // 執行完上面的任務后,不改變原有的sql執行過程
  return invocation.proceed();
 }
 
 // 封裝了一下sql語句,使得結果返回完整xml路徑下的sql語句節點id + sql語句
 public static String getSql(Configuration configuration, BoundSql boundSql, String sqlId)
 {
  String sql = showSql(configuration, boundSql);
  StringBuilder str = new StringBuilder(100);
  str.append(sqlId);
  str.append(":");
  str.append(sql);
  return str.toString();
 }
 
 // 如果參數是String,則添加單引號, 如果是日期,則轉換為時間格式器并加單引號; 對參數是null和不是null的情況作了處理
 private static String getParameterValue(Object obj)
 {
  String value = null;
  if (obj instanceof String)
  {
   value = "'" + obj.toString() + "'";
  }
  else if (obj instanceof Date)
  {
   DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,
    DateFormat.DEFAULT, Locale.CHINA);
   value = "'" + formatter.format(new Date()) + "'";
  }
  else
  {
   if (obj != null)
   {
    value = obj.toString();
   }
   else
   {
    value = "";
   } 
  }
  return value;
 }
 
 // 進行?的替換
 public static String showSql(Configuration configuration, BoundSql boundSql)
 {
  // 獲取參數
  Object parameterObject = boundSql.getParameterObject();
  List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  // sql語句中多個空格都用一個空格代替
  String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
  if (CollectionUtils.isNotEmpty(parameterMappings) && parameterObject != null)
  {
   // 獲取類型處理器注冊器,類型處理器的功能是進行java類型和數據庫類型的轉換
   TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
   // 如果根據parameterObject.getClass()可以找到對應的類型,則替換
   if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass()))
   {
    sql = sql.replaceFirst("\\&#63;",
     Matcher.quoteReplacement(getParameterValue(parameterObject))); 
   }
   else
   {
    // MetaObject主要是封裝了originalObject對象,提供了get和set的方法用于獲取和設置originalObject的屬性值,主要支持對JavaBean、Collection、Map三種類型對象的操作
    MetaObject metaObject = configuration.newMetaObject(parameterObject);
    for (ParameterMapping parameterMapping : parameterMappings)
    {
     String propertyName = parameterMapping.getProperty();
     if (metaObject.hasGetter(propertyName))
     {
      Object obj = metaObject.getValue(propertyName);
      sql = sql.replaceFirst("\\&#63;",
       Matcher.quoteReplacement(getParameterValue(obj)));
     }
     else if (boundSql.hasAdditionalParameter(propertyName))
     {
      // 該分支是動態sql
      Object obj = boundSql.getAdditionalParameter(propertyName);
      sql = sql.replaceFirst("\\&#63;",
       Matcher.quoteReplacement(getParameterValue(obj)));
     }
     else
     {
      // 打印出缺失,提醒該參數缺失并防止錯位
      sql = sql.replaceFirst("\\&#63;", "缺失");
     }
    }
   }
  }
  return sql;
 }
 
 @Override
 public Object plugin(Object target)
 {
  return Plugin.wrap(target, this);
 }
 
 @Override
 public void setProperties(Properties properties)
 {
 
 } 
}

打印結果攔截器:

import java.util.Properties; 
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds; 
import com.poly.rbl.utils.FastJsonUtils; 
 
/**
 * 打印結果攔截器 〈功能詳細描述〉
 * 
 * @author gogym
 * @version 2019年4月2日
 * @see InterceptorForQry
 * @since
 */
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class,
 Object.class, RowBounds.class, ResultHandler.class})})
public class InterceptorForQry implements Interceptor
{
 
 @SuppressWarnings({"rawtypes", "unchecked"})
 public Object intercept(Invocation invocation)
  throws Throwable
 {
  Object result = invocation.proceed(); // 執行請求方法,并將所得結果保存到result中
  String str = FastJsonUtils.toJSONString(result);
  System.out.println(str);
  return result;
 }
 
 public Object plugin(Object target)
 {
  return Plugin.wrap(target, this);
 }
 
 public void setProperties(Properties arg0)
 {}
}

用法直接配置在mybatis配置文件里面即可:

<plugins> 
 <!-- 啟動SQL打印,帶參數 
   <plugin interceptor="com.poly.rbl.plugin.mybatis.MybatisInterceptor">
 </plugin>
 
    <plugin interceptor="com.poly.rbl.plugin.mybatis.InterceptorForQry">
 </plugin> 
 </plugins>

上述內容就是mybatis 通過攔截器實現打印完整的sql語句并執行結果,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武川县| 易门县| 什邡市| 东方市| 成安县| 南漳县| 盐池县| 唐河县| 那曲县| 哈巴河县| 讷河市| 沿河| 青海省| 华安县| 辛集市| 商城县| 灵川县| 新平| 侯马市| 湘潭市| 三门峡市| 惠州市| 临澧县| 闽清县| 达州市| 永济市| 尼玛县| 华坪县| 鄯善县| 遂宁市| 永嘉县| 周至县| 台南市| 宿松县| 尚义县| 南丹县| 石河子市| 塘沽区| 新营市| 英德市| 烟台市|