在開發專案時,我們通常會很在意 SQL 的執行狀況,像是
- 想知道 SQL 執行的效能如何
- 實際在資料庫執行的 SQL 內容為何
- 使用 JDBC prepared statement時 “?”參數的內容
- OR mapping 工具最後產生的 SQL 語句內容
當然我們也可以自己加幾行程式碼來取得這些資訊,但大家可以想一想,這些用來純粹取得 SQL 執行內容的程式碼,無關任何業務邏輯,這樣的程式碼放在專案裡真的好嗎?修改幅度不大的話,或許可以這麼做。但如果是有點規模的專案,光是加這些監控的程式碼就是一項很耗費時間的工作,再加上一個不小心動到原本正常執行的程式,那更是得不償失!
今天要介紹一個工具:p6spy,只要透過幾個簡單設定,就可以觀察所有 SQL 的執行狀況,而且移除也很容易,非常適合專案在開發階段時使用!
- 請 clone 以下專案
https://github.com/kennyliao1982/demo-p6spy - 匯入 Eclipse 之後,執行 mvn package,確保需要的 dependency 都有抓到
- 執行 src/main/java 底下的 com.appx.demo.p6spy.App.java
- 觀察 console
大家可以看到 log 的上半部記載了 SQL 執行狀況,log的格式如下:(以”|”分隔)
執行當下時間 | 執行耗費時間 | log種類 | connection id | prepared statement SQL語句
實際執行的SQL語句
這次的測試一樣使用了H2 database + Hikari connection pool,主要執行流程如下:
(可參考App.java 的 main 方法)
- 啟動資料庫
- 建立 DataSource,新建 user table,新增幾筆 user 資料
- 查詢所有 user資料
- 關閉資料庫
大部分的操作都和之前在示範 connection pool 時一樣,究竟在哪裡用到 p6spy 呢?答案在 App.java 第61行
對,程式碼的異動,就只有這麼一行!這一行只是把原本建立好的 HikariDataSource 物件用 p6spy 提供的 P6DataSource 包裝起來,後續的參數一律使用 P6DataSource,這樣就達到 SQL logging 的效果了!( log 輸出格式的設定可以參考 src/main/resources/spy.properties,基本上都用預設值)
P6DataSource 針對原有 DataSource 作了包裝並加上 logging 機制,實現了 design pattern 中的 decorator pattern (另一個典型例子就是 Java IO 的 BufferedReader )
我們這個案例是手動建立資料庫連線,所以使用 p6spy 需要動一點程式碼,如果是在使用了 framework 的架構下,基本上資料庫連線都是由 framework 讀取設定後負責建立的,這種情況下要使用 p6spy 只需動動設定檔就好,對於程式碼來說沒有任何影響,之後要移除也是非常容易!