最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mybatis 通過(guò)攔截器打印完整的sql語(yǔ)句以及執(zhí)行結(jié)果操作

 更新時(shí)間:2020年10月09日 11:22:38   作者:Gogym  
這篇文章主要介紹了mybatis 通過(guò)攔截器打印完整的sql語(yǔ)句以及執(zhí)行結(jié)果操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

開(kāi)發(fā)過(guò)程中,如果使用mybatis做為ORM框架,經(jīng)常需要打印出完整的sql語(yǔ)句以及執(zhí)行的結(jié)果做為參考。

雖然mybatis結(jié)合日志框架可以做到,但打印出來(lái)的通常都是sql和參數(shù)分開(kāi)的。

有時(shí)我們需要調(diào)試這條sql的時(shí)候,就需要把參數(shù)填進(jìn)去,這樣未免有些浪費(fèi)時(shí)間。

此時(shí)我們可以通過(guò)實(shí)現(xiàn)mybatis攔截器來(lái)做到打印帶參數(shù)的完整的sql,以及結(jié)果通過(guò)json輸出到控制臺(tái)。

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

MyBatis攔截器打印不帶問(wèn)號(hào)的完整sql語(yǔ)句攔截器

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攔截器打印不帶問(wèn)號(hào)的完整sql語(yǔ)句
 * 
 * @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中的一個(gè)select/update/insert/delete節(jié)點(diǎn),是一條SQL語(yǔ)句
   MappedStatement mappedStatement = (MappedStatement)invocation.getArgs()[0];
   Object parameter = null;
   // 獲取參數(shù),if語(yǔ)句成立,表示sql語(yǔ)句有參數(shù),參數(shù)格式是map形式
   if (invocation.getArgs().length > 1)
   {
    parameter = invocation.getArgs()[1];
    System.out.println("parameter = " + parameter);
   }
   String sqlId = mappedStatement.getId(); // 獲取到節(jié)點(diǎn)的id,即sql語(yǔ)句的id
   System.out.println("sqlId = " + sqlId);
   BoundSql boundSql = mappedStatement.getBoundSql(parameter); // BoundSql就是封裝myBatis最終產(chǎn)生的sql類
   Configuration configuration = mappedStatement.getConfiguration(); // 獲取節(jié)點(diǎn)的配置
   String sql = getSql(configuration, boundSql, sqlId); // 獲取到最終的sql語(yǔ)句
   System.out.println("sql = " + sql);
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }
  // 執(zhí)行完上面的任務(wù)后,不改變?cè)械膕ql執(zhí)行過(guò)程
  return invocation.proceed();
 }
 
 // 封裝了一下sql語(yǔ)句,使得結(jié)果返回完整xml路徑下的sql語(yǔ)句節(jié)點(diǎn)id + sql語(yǔ)句
 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();
 }
 
 // 如果參數(shù)是String,則添加單引號(hào), 如果是日期,則轉(zhuǎn)換為時(shí)間格式器并加單引號(hào); 對(duì)參數(shù)是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;
 }
 
 // 進(jìn)行?的替換
 public static String showSql(Configuration configuration, BoundSql boundSql)
 {
  // 獲取參數(shù)
  Object parameterObject = boundSql.getParameterObject();
  List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  // sql語(yǔ)句中多個(gè)空格都用一個(gè)空格代替
  String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
  if (CollectionUtils.isNotEmpty(parameterMappings) && parameterObject != null)
  {
   // 獲取類型處理器注冊(cè)器,類型處理器的功能是進(jìn)行java類型和數(shù)據(jù)庫(kù)類型的轉(zhuǎn)換
   TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
   // 如果根據(jù)parameterObject.getClass()可以找到對(duì)應(yīng)的類型,則替換
   if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass()))
   {
    sql = sql.replaceFirst("\\?",
     Matcher.quoteReplacement(getParameterValue(parameterObject))); 
   }
   else
   {
    // MetaObject主要是封裝了originalObject對(duì)象,提供了get和set的方法用于獲取和設(shè)置originalObject的屬性值,主要支持對(duì)JavaBean、Collection、Map三種類型對(duì)象的操作
    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("\\?",
       Matcher.quoteReplacement(getParameterValue(obj)));
     }
     else if (boundSql.hasAdditionalParameter(propertyName))
     {
      // 該分支是動(dòng)態(tài)sql
      Object obj = boundSql.getAdditionalParameter(propertyName);
      sql = sql.replaceFirst("\\?",
       Matcher.quoteReplacement(getParameterValue(obj)));
     }
     else
     {
      // 打印出缺失,提醒該參數(shù)缺失并防止錯(cuò)位
      sql = sql.replaceFirst("\\?", "缺失");
     }
    }
   }
  }
  return sql;
 }
 
 @Override
 public Object plugin(Object target)
 {
  return Plugin.wrap(target, this);
 }
 
 @Override
 public void setProperties(Properties properties)
 {
 
 } 
}

打印結(jié)果攔截器:

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; 
 
/**
 * 打印結(jié)果攔截器 〈功能詳細(xì)描述〉
 * 
 * @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(); // 執(zhí)行請(qǐng)求方法,并將所得結(jié)果保存到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> 
 <!-- 啟動(dòng)SQL打印,帶參數(shù) 
   <plugin interceptor="com.poly.rbl.plugin.mybatis.MybatisInterceptor">
 </plugin>
 
    <plugin interceptor="com.poly.rbl.plugin.mybatis.InterceptorForQry">
 </plugin> 
 </plugins>

以上這篇mybatis 通過(guò)攔截器打印完整的sql語(yǔ)句以及執(zhí)行結(jié)果操作就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot整合jcasbin權(quán)限管理

    springboot整合jcasbin權(quán)限管理

    jcasbin的權(quán)限控制非常簡(jiǎn)單,本文就來(lái)介紹一下springboot整合jcasbin權(quán)限管理,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • SpringBoot攔截器實(shí)現(xiàn)登錄攔截的示例代碼

    SpringBoot攔截器實(shí)現(xiàn)登錄攔截的示例代碼

    本文主要介紹了SpringBoot攔截器實(shí)現(xiàn)登錄攔截,文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 解決springboot遇到autowire注入為null的問(wèn)題

    解決springboot遇到autowire注入為null的問(wèn)題

    這篇文章主要介紹了解決springboot遇到autowire注入為null的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • 使用Spring注入Hibernate驗(yàn)證框架

    使用Spring注入Hibernate驗(yàn)證框架

    這篇文章主要介紹了使用Spring注入Hibernate驗(yàn)證框架方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • SpringBoot如何基于POI-tl和word模板導(dǎo)出龐大的Word文件

    SpringBoot如何基于POI-tl和word模板導(dǎo)出龐大的Word文件

    這篇文章主要介紹了SpringBoot如何基于POI-tl和word模板導(dǎo)出龐大的Word文件,poi-tl是一個(gè)基于Apache?POI的Word模板引擎,也是一個(gè)免費(fèi)開(kāi)源的Java類庫(kù)
    2022-08-08
  • Spring IOC的相關(guān)注解運(yùn)用詳解

    Spring IOC的相關(guān)注解運(yùn)用詳解

    這篇文章主要介紹了Spring IOC的相關(guān)注解運(yùn)用詳解,純注解實(shí)現(xiàn)IOC需要一個(gè)Java類代替xml文件,這個(gè)Java類上方需要添加@Configuration,表示該類是一個(gè)配置類,作用是代替配置文件,需要的朋友可以參考下
    2023-08-08
  • 詳解使用Spring?Data?repository進(jìn)行數(shù)據(jù)層的訪問(wèn)問(wèn)題

    詳解使用Spring?Data?repository進(jìn)行數(shù)據(jù)層的訪問(wèn)問(wèn)題

    這篇文章主要介紹了使用Spring?Data?repository進(jìn)行數(shù)據(jù)層的訪問(wèn),抽象出Spring Data repository是因?yàn)樵陂_(kāi)發(fā)過(guò)程中,常常會(huì)為了實(shí)現(xiàn)不同持久化存儲(chǔ)的數(shù)據(jù)訪問(wèn)層而寫(xiě)大量的大同小異的代碼,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2022-06-06
  • springboot使用kafka事務(wù)的示例代碼

    springboot使用kafka事務(wù)的示例代碼

    Kafka?同數(shù)據(jù)庫(kù)一樣支持事務(wù),當(dāng)發(fā)生異常的時(shí)候可以進(jìn)行回滾,確保消息監(jiān)聽(tīng)器不會(huì)接收到一些錯(cuò)誤的或者不需要的消息,本文就來(lái)介紹一下springboot使用kafka事務(wù)的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • 新手了解java 數(shù)組基礎(chǔ)知識(shí)

    新手了解java 數(shù)組基礎(chǔ)知識(shí)

    這篇文章主要介紹了Java 數(shù)組分析及簡(jiǎn)單實(shí)例的相關(guān)資料,在Java中它就是對(duì)象,一個(gè)比較特殊的對(duì)象,需要的朋友可以參考下,希望可以對(duì)你有所幫助
    2021-07-07
  • 新版idea創(chuàng)建spring boot項(xiàng)目的詳細(xì)教程

    新版idea創(chuàng)建spring boot項(xiàng)目的詳細(xì)教程

    這篇文章給大家介紹了新版idea創(chuàng)建spring boot項(xiàng)目的詳細(xì)教程,本教程對(duì)新手小白友好,若根據(jù)教程創(chuàng)建出現(xiàn)問(wèn)題導(dǎo)致失敗可下載我提供的源碼,在文章最后,本教程較新,文中通過(guò)圖文給大家介紹的非常詳細(xì),感興趣的朋友可以參考下
    2024-01-01

最新評(píng)論

烟台市| 龙海市| 镇雄县| 黄梅县| 黎平县| 梅州市| 萝北县| 格尔木市| 邮箱| 格尔木市| 舟山市| 馆陶县| 咸丰县| 辽宁省| 随州市| 安化县| 田阳县| 马公市| 交城县| 敖汉旗| 肃北| 赤峰市| 白河县| 阜新| 枣阳市| 桑日县| 新龙县| 观塘区| 安康市| 石渠县| 汤原县| 化隆| 万盛区| 嘉禾县| 南木林县| 兰州市| 芮城县| 南郑县| 苍山县| 灵丘县| 陆河县|