成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

換種方式,打印 MyBatis 執(zhí)行 SQL 語句!

數據庫 其他數據庫
你是否有在使用 IntelliJ IDEA 做開發(fā)的過程,需要拿到執(zhí)行 SQL 語句,復制出來做驗證的時候,總是這樣的語句:SELECT * FROM USER WHERE id = ? AND name = ? 又需要自己把 ? 號 替換成入參值呢?

一、前言

片面了!

一月三舟,托爾斯泰說:“多么偉大的作家,也不過就是在書寫自己的片面而已”。何況是我,何況是我們!

雖然我們不書寫文章,但我們寫需求、寫代碼、寫注釋,當我們遇到了需要被討論的問題點時,往往變成了爭論點。這個好、那個差、你用的都是啥啥啥!

當你把路走窄了,你所能接受到的新的思路、新的想法、新的視野,以及非常重要的收入,也都會隨之減少。只有橫向對比、參考借鑒、查漏補缺,才能讓你的頭腦中會有更多的思路,無論是在寫代碼上、還是在理財上、還是在生活上。

二、需求目的

你是否有在使用 IntelliJ IDEA 做開發(fā)的過程,需要拿到執(zhí)行 SQL 語句,復制出來做驗證的時候,總是這樣的語句:SELECT * FROM USER WHERE id = ? AND name = ? 又需要自己把 ? 號 替換成入參值呢?

當然這個需求其實并不大,甚至你還可以使用其他方式解決。那么在本章節(jié)會給你提供一個新的思路,可能你幾乎是沒過的方式進行處理。

那么在這個章節(jié)的案例中我們用到基于 IDEA Plugin 開發(fā)能力,把字節(jié)碼插樁探針,基于 Javaagent 的能力,注入到代碼中。再通過增強后的字節(jié)碼,獲取到 com.mysql.jdbc.PreparedStatement -> executeInternal 執(zhí)行時的對象,從而拿到可以直接測試的 SQL 語句。

三、案例開發(fā)

1. 工程結構

guide-idea-plugin-probe
├── .gradle
├── probe-agent
│ ├── src
│ │ └── main
│ │ └── java
│ │ └── cn.bugstack.guide.idea.plugin
│ │ ├── MonitorMethod.java
│ │ └── PreAgent.java
│ └── build.gradle
└── probe-plugin
│ └── src
│ │ └── main
│ │ ├── java
│ │ │ └── cn.bugstack.guide.idea.plugin
│ │ │ └── utils
│ │ │ │ └── PluginUtil.java
│ │ │ └── PerRun.java
│ │ └── resources
│ │ └── META-INF
│ │ └── plugin.xml
│ └── build.gradle
├── build.gradle
└── gradle.properties

公眾號:bugstack蟲洞棧 回復:idea 即可下載全部 IDEA 插件開發(fā)源碼

在此 IDEA 插件工程中,工程結構分為2塊:

  • probe-agent:探針模塊,用于編譯打包提供字節(jié)碼增強服務,給 probe-plugin 模塊使用
  • probe-plugin:插件模塊,通過 java.programPatcher加載字節(jié)碼增強包,獲取并打印執(zhí)行數據庫操作的 SQL 語句。

2. 字節(jié)碼增強獲取 SQL

此處的字節(jié)碼增強方式,采用的 Byte-Buddy 字節(jié)碼框架,它的使用方式更加簡單,在使用的過程中有些像使用 AOP 的攔截方式一樣,獲取到你需要的信息。

此外在 gradle 打包構建的時候,需要添加 shadowJar 模塊,把 Premain-Class 打包進去。這部分代碼中可以查看

2.1 探針入口

cn.bugstack.guide.idea.plugin.PreAgent

//JVM 首先嘗試在代理類上調用以下方法
public static void premain(String agentArgs, Instrumentation inst){
AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, javaModule) -> {
return builder
.method(ElementMatchers.named("executeInternal")) // 攔截任意方法
.intercept(MethodDelegation.to(MonitorMethod.class)); // 委托
};
new AgentBuilder
.Default()
.type(ElementMatchers.nameStartsWith("com.mysql.jdbc.PreparedStatement"))
.transform(transformer)
.installOn(inst);
}
  • 通過 Byte-buddy 配置,攔截匹配的類和方法,因為這個類和方法下,可以獲取到完整的執(zhí)行 SQL 語句。

2.2 攔截 SQL

cn.bugstack.guide.idea.plugin.MonitorMethod

@RuntimeType
public static Object intercept(@This Object obj, @Origin Method method, @SuperCall Callable<?> callable, @AllArguments Object... args) throws Exception {
try {
return callable.call();
} finally {
String originalSql = (String) BeanUtil.getFieldValue(obj, "originalSql");
String replaceSql = ReflectUtil.invoke(obj, "asSql");
System.out.println("數據庫名稱:Mysql");
System.out.println("線程ID:" + Thread.currentThread().getId());
System.out.println("時間:" + new Date());
System.out.println("原始SQL:\r\n" + originalSql);
System.out.println("替換SQL:\r\n" + replaceSql);
}
}
  • 攔截方法入參是一種可配置操作,比如 @This Object obj是為了獲取當前類的執(zhí)行對象,@Origin Method method是為了獲取執(zhí)行方法。
  • 在 finally 塊中,我們可以通過反射拿到當前類的屬性信息,以及反射拿到執(zhí)行的 SQL,并做打印輸出。

2.3 編譯打包

在測試和開發(fā) IDEA Plugin 插件之前,我們需要先進行一個打包操作,這個打包就是把字節(jié)碼增強的代碼打包整一個 Jar 包。在 build.gradle -> shadowJar

  • 打包編譯后,就可以在 build -> libs 下看到 Jar:probe-agent-1.0-SNAPSHOT-all.jar這個 Jar 就是用來做字節(jié)碼增強處理的。

2.4 測試驗證

這里在把寫好的字節(jié)碼增強組件給插件使用之前,可以做一個測試驗證,避免每次都需要啟動插件才能做測試。

單元測試

public class ApiTest {

public static void main(String[] args) throws Exception {

String URL = "jdbc:mysql://127.0.0.1:3306/itstack?characterEncoding=utf-8";
String USER = "root";
String PASSWORD = "123456";
Class.forName("com.mysql.jdbc.Driver");

Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
String sql="SELECT * FROM USER WHERE id = ? AND name = ?";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setLong(1,1L);
statement.setString(2,"謝飛機");
ResultSet rs = statement.executeQuery();

while (rs.next()) {
System.out.println(rs.getString("name") + " " + rs.getString("address"));
}

}

}
  • VM options:-javaagent:你的路徑\libs\probe-agent-1.0-SNAPSHOT-all.jar
  • 注意在測試運行的時候,你要給 ApiTest 配置 VM options 才能打印攔截 SQL 信息

測試結果

原始SQL:
SELECT * FROM USER WHERE id = ? AND name = ?
替換SQL:
SELECT * FROM USER WHERE id = 1 AND name = '謝飛機'
謝飛機 北京.大興區(qū).通明湖公園
  • 好啦,這樣我們就可以攔截可以復制執(zhí)行的 SQL 語句了,接下來我們再做下 IDEA Plugin 的處理。

3. 通過插件開發(fā)引入探針 Jar

接下來我們要把開發(fā)好的字節(jié)碼增強 Jar 包,復制到 IDEA Plugin 插件開發(fā)模塊中的 libs(可自己創(chuàng)建) 下,之后在 plugin.xml 配置加載 implementation fileTree(dir: 'libs', includes: ['*jar']) 這樣就可以程序中,找到這個 jar 包并配置到程序中。

3.1 復制 jar 到 libs 下

3.2 build.gradle 配置加載

dependencies {
implementation fileTree(dir: 'libs', includes: ['*jar'])
}
  • 通過 implementation fileTree引入加載文件樹的方式,把我們配置好的 Jar 加載到程序運行中。

3.3 程序中引入 javaagent

cn.bugstack.guide.idea.plugin.PerRun

public class PerRun extends JavaProgramPatcher {

@Override
public void patchJavaParameters(Executor executor, RunProfile configuration, JavaParameters javaParameters){

RunConfiguration runConfiguration = (RunConfiguration) configuration;
ParametersList vmParametersList = javaParameters.getVMParametersList();
vmParametersList.addParametersString("-javaagent:" + agentCoreJarPath);
vmParametersList.addNotEmptyProperty("guide-idea-plugin-probe.projectId", runConfiguration.getProject().getLocationHash());

}

}
  • 通過繼承 JavaProgramPatcher類,實現patchJavaParameters方法,通過 configuration 屬性來配置我們自己需要被加載的-javaagent包。
  • 這樣在通過 IDEA 已經安裝此插件,運行代碼的時候,就會執(zhí)行到這個攔截和打印 SQL 的功能。

3.4 plugin.xml 添加配置

<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<java.programPatcher implementation="cn.bugstack.guide.idea.plugin.PerRun"/>
</extensions>
  • 之后你還需要把開發(fā)好的加載類,配置到 java.programPatcher這樣就可以程序運行的時候,被加載到了。

四、測試驗證

  • 準備好一個有數據庫操作的工程,需要的是 JDBC,如果是其他的,你需要自己擴展
  • 啟動插件后,打開你的工程,運行單元測試,查看打印區(qū)

啟動插件

  • 如果你是新下載代碼,那么可以在 probe-plugin -> Tasks -> intellij -> runIde 中進行運行啟動。

單元測試

@Test
public void test_update(){
User user = new User();
user.setId(1L);
user.setName("謝飛機");
user.setAge(18);
user.setAddress("北京.大興區(qū).亦莊經濟開發(fā)區(qū)");
userDao.update(user);
}

測試結果

22:30:55.593 [main] DEBUG cn.bugstack.test.demo.infrastructure.dao.UserDao.update[143] - ==>  Preparing: UPDATE user SET name=?,age=?,address=? WHERE id=? 
22:30:55.625 [main] DEBUG cn.bugstack.test.demo.infrastructure.dao.UserDao.update[143] - ==> Parameters: 謝飛機(String), 18(Integer), 北京.大興區(qū).亦莊經濟開發(fā)區(qū)(String), 1(Long)
數據庫名稱:Mysql
線程ID:1
原始SQL:
UPDATE user SET name=?,age=?,address=?
WHERE id=?
替換SQL:
UPDATE user SET name='謝飛機',age=18,address='北京.大興區(qū).亦莊經濟開發(fā)區(qū)'
WHERE id=1
  • 通過測試結果可以看到,我們可以獲取到直接拿去測試驗證的 SQL 語句了,就不用在復制帶問號的 SQL 還得修改后測試了。

五、總結

  • 首先我們是在本章節(jié)初步嘗試使用多模塊的方式來創(chuàng)建工程,這樣的方式可以更加好維護各類一個工程下所需要的代碼模塊。你也可以嘗試使用 gradle 創(chuàng)建多模塊工程
  • 對于字節(jié)碼插樁增強的使用方式,本篇只是一個介紹,這項技術還可以運用到更多的場景,開發(fā)出各種提升研發(fā)效率的工具。
  • 了解額外的 Jar 包是怎么加載到工程的,以及如何通過配置的方式讓 javaagent引入自己開發(fā)好的探針組件。
責任編輯:武曉燕 來源: 今日頭條
相關推薦

2024-02-04 09:24:45

MyBatisSQL語句Spring

2010-11-12 11:48:15

2010-11-24 08:54:33

2010-11-04 09:43:46

LINQ to SQL

2018-04-28 15:51:33

Mybatis方式傳遞

2010-09-25 14:38:29

SQL分頁

2010-09-03 14:47:50

SQLSELECT語句

2010-09-25 14:59:54

SQL語句

2024-12-26 08:16:26

2010-04-29 14:06:40

Oracle SQL

2021-07-28 07:22:40

SQL順序Hive

2010-09-25 16:21:41

SQL語句

2019-11-06 09:30:35

SQL查詢語句數據庫

2010-10-21 16:24:18

sql server升

2022-10-18 10:41:44

Flowable服務任務

2024-01-17 13:56:00

Redis節(jié)點映射關系

2010-09-27 10:55:01

SQL事件探查器

2022-10-28 11:04:24

Python映射容器

2022-09-01 16:42:47

MySQL數據庫架構

2010-09-07 14:45:34

sql語句
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 羞羞视频网站免费观看 | 欧美日韩不卡合集视频 | 亚洲成人一级 | 久久久精品网站 | 亚洲一区二区三区四区五区午夜 | 日日干天天操 | 人人干97 | 在线免费看91 | 日韩免费电影 | 亚洲人成人一区二区在线观看 | 精品无码久久久久久国产 | 一级做a爰片性色毛片 | 99久久久久| 欧美日韩淫片 | 国产精品亚洲精品日韩已方 | 特级黄一级播放 | 日日夜夜操天天干 | 成人av在线播放 | 日本福利视频免费观看 | 国产专区在线 | 伊人二区 | 激情小视频 | 国产视频1区 | www.久| 日本一本视频 | 亚洲精品91| 日韩免费一级 | 欧美成人a∨高清免费观看 欧美日韩中 | 啪啪av| 999久久久久久久久 国产欧美在线观看 | 欧美日韩国产在线 | 欧美精品网站 | 国产黄色大片在线免费观看 | 国产乱精品一区二区三区 | av天天澡天天爽天天av | 精品视频999| 久久lu| 国产成人av在线播放 | 国产精品成人一区二区三区 | 天天躁人人躁人人躁狂躁 | 日韩综合网 |