Statement。? 佔位符防止 SQL 注入,型別安全,自動處理引號/轉義。addBatch()/executeBatch() 大幅提升批量寫入效能。PreparedStatement pstmt = con.prepareStatement(
"UPDATE table4 SET m = ? WHERE x = ?");
// 參數索引從 1 開始
pstmt.setLong(1, 123456789); // 對應第一個 ?
pstmt.setLong(2, 100000000); // 對應第二個 ?
設置參數後可多次執行,直到調用 clearParameters() 重置。自動提交模式下每次執行自動提交/回滾。
pstmt.setString(1, "Hi"); // 固定參數
for (int i = 0; i < 10; i++) {
pstmt.setInt(2, i); // 變動參數
pstmt.executeUpdate();
}
前提:資料庫/驅動在提交後保持 Statement 開啟 (多數現代驅動支援),否則無法復用。
setXXX 方法名對應 Java 型別,驅動自動映射至標準 JDBC 型別 (參考 JDBC 規範 8.6.2 映射表)。
| Java 型別 | setXXX 方法 | 標準 JDBC 型別 |
|---|---|---|
short | setShort | SMALLINT |
int | setInt | INTEGER |
long | setLong | BIGINT |
float | setFloat | REAL |
double | setDouble | DOUBLE |
String | setString | VARCHAR |
byte[] | setBytes | VARBINARY |
Date | setDate | DATE |
Timestamp | setTimestamp | TIMESTAMP |
開發者責任:確保 Java 型別映射的 JDBC 型別與資料庫欄位定義相容。如資料庫需 SMALLINT,用 setByte (TINYINT) 通常可隱式轉換,但嚴格匹配最安全。
executeQuery():返回 ResultSet (SELECT)。executeUpdate():返回影響行數 (INSERT/UPDATE/DELETE/DDL)。execute():通用執行,可能返回多結果集,需配合 getResultSet()/getUpdateCount()/getMoreResults() 處理。禁用:Statement 版本的帶 SQL 字串重載方法 (executeQuery(sql) 等),會拋出異常或忽略預編譯優勢。
// 不安全 - 字串拼接
stmt.executeUpdate("SELECT * FROM users WHERE name = '" + userInput + "'");
// 輸入: ' OR '1'='1 → 全表查詢
// 安全 - 參數化
pstmt = con.prepareStatement("SELECT * FROM users WHERE name = ?");
pstmt.setString(1, userInput); // 輸入被視為字面值,不解析 SQL
prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) → getGeneratedKeys() 獲取自增主鍵。prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY) 實現可捲動結果集。addBatch 累積、executeBatch 一次性提交、捕獲 BatchUpdateException 處理部分失敗。