天天看點

PrepareStatement 如何列印真實 SQL

我們知道,JDBC 的 PrepareStatement 優點多多,通常都是推薦使用 PrepareStatement 而不是其基類 Statment。PrepareStatement 支援 ? 占位符,可以将參數按照類型轉自動換為真實的值。既然這一過程是自動的,封裝在 JDBC 内部的,那麼我們外部就不得而知目标的 SQL 最終生成怎麼樣——于是在調試過程中便有一個列印 SQL 的問題。我們對 PrepareStatement 傳入 SQL 語句,如 SELECT * FROM table WHERE id = ?,然後我們傳入對應的 id 參數,假設是 id = 10,那怎麼把得到參數的 SELECT * FROM table WHERE id =  12 結果完整地得出來呢?——這便是本文所要探讨的問題。

首先,我們看看典型的一個 PrepareStatement 調用方法,如下一個函數,

值得注意該函數裡面:

其參數一 sql 就是類似 SELECT * FROM table WHERE id = ? 的語句,參數二 params 為 Object... params 的參數清單,可以是任意類似的合法 SQL 值。最後,通過 printRealSql 函數最終得出形如 SELECT * FROM table WHERE id =  12 的結果。

printRealSql 函數源碼如下:

可見,上述思路是非常簡單的,——有多少個 ? 占位符,就要求有多少個參數,然後一一對照填入(數組)。match 函數會檢查第一個步驟,檢查個數是否比對,否則會傳回“SQL 語句中的占位符與參數個數不比對”的提示;然後,參數的值會被轉換為符合 SQL 值所要求的類型;最後,就是将 SQL 一一填入,——此處使用了一個字元串的技巧,先把 ? 字元通通轉換為 %s,——那是 String.format 可識别的占位符,如此再傳入 Object[] 參數清單,即可得出我們期待的 SQL 結果。

我們不能保證那 SQL 可以直接放到資料庫中被解析。因為我們的初衷隻是把 SQL 列印出來,務求更近一步讓程式員在開發階段看到 SQL 是怎麼樣子的,而且不是一堆 ?、?……,這樣會顯得更符合真實情形一點。

PrepareStatement 内部源碼肯定有這一步驟或者某個變量是表示那個真實 SQL 的,——隻是沒有暴露出來。如果有,那麼對程式員會更友好一些。