許多開發者僅將 JDBC 視為 ORM 底層,實則 JDBC 2.0~4.0 引入的進階特性能直接解決可擴展性與開發效率痛點。本文系統梳理 5 大核心進階功能。
JDBC 規範定義標準函數語法 `{fn ...}`,驅動程式負責轉譯為目標資料庫方言。範例:
ResultSet rs = stmt.executeQuery("{CURRENT_DATE()}"); // 取得當前日期
ResultSet rs = stmt.executeQuery("{CONCAT(first_name, ' ', last_name)}"); // 字串串接
透過 `DatabaseMetaData` 查詢支援清單:
String numericFns = dbmd.getNumericFunctions(); // 數值函數
String stringFns = dbmd.getStringFunctions(); // 字串函數
String systemFns = dbmd.getSystemFunctions(); // 系統函數
String timeFns = dbmd.getTimeDateFunctions(); // 時間日期函數
回傳逗號分隔字串,`split(",")` 即得可測試清單。
建立時指定類型:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, // 可捲動,不反映他人提交的變更
ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("SELECT * FROM whatever");
三種捲動類型:
導航方法:`previous()`、`first()`、`last()`、`absolute(n)`、`relative(n)`、`getRow()`、`setFetchDirection()`。
第二參數指定 `CONCUR_UPDATABLE`:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT * FROM lineitem WHERE id=1");
rs.first();
rs.updateFloat("PRICE", 121.45f);
if (userSaidOK) rs.updateRow(); else rs.cancelRowUpdates();
新增列:`moveToInsertRow()` → `updateXxx()` → `insertRow()`。刪除:`deleteRow()`。同樣適用於 `PreparedStatement`(防 SQL 注入)。
解決可捲動/可更新需長連線的擴展性難題。五種介面實作:
| 類型 | 連線模式 | 特色 |
|---|---|---|
| JdbcRowSet | 連線 | ResultSet 直接封裝 |
| CachedRowSet | 離線 | 基礎離線實作 |
| WebRowSet | 離線 | 支援 XML 序列化/反序列化 |
| JoinRowSet | 離線 | 無連線執行 SQL JOIN |
| FilteredRowSet | 離線 | 客戶端進一步過濾 |
用法:
CachedRowSet crs = new CachedRowSetImpl();
crs.populate(rs); // 從 ResultSet 填充
// 斷線後仍可捲動、更新、插入、刪除
crs.acceptChanges(); // 重連時批量同步回資料庫
RowSet 為完整 JavaBeans,支援屬性設定(URL、用戶、密碼、DataSource、Command)、事件監聽、自主執行 `execute()`。
驅動支援檢查:`dbmd.supportsBatchUpdates()`。流程:
conn.setAutoCommit(false);
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO lineitems VALUES(?,?,?,?)");
for (LineItem item : items) {
pstmt.setInt(1, item.id);
pstmt.setString(2, item.sku);
pstmt.setFloat(3, item.price);
pstmt.setBoolean(4, item.active);
pstmt.addBatch();
}
int[] updateCounts = pstmt.executeBatch(); // 一次性送出
conn.commit();
conn.setAutoCommit(true);
回傳 `int[]` 對應各條 `executeUpdate()` 結果。異常拋 `BatchUpdateException`,驅動行為不一(可能繼續/停止),需實測驗證。