代碼邏輯無誤、無異常拋出,但數據庫記錄未更新/插入。
| 檢查點 | 錯誤表現 | 正確做法 |
|---|---|---|
| 自動提交關閉 | conn.setAutoCommit(false)後未commit() | 執行完DML必須 `conn.commit()` |
| PreparedStatement參數索引 | setString(1, val) 但SQL佔位符從0開始 | JDBC參數索引**從1開始** |
| SQL語句拼接 | 字符串拼接導致注入/語法錯誤 | 全程使用 `?` 佔位符 + setXxx() |
| 異常吞噬 | catch塊只打印堆疊,不回滾、不拋出 | catch中 `conn.rollback()` 並重新拋出 |
| 連接池泄漏 | 連接未歸還導致事務懸掛 | try-with-resources 自動關閉 |
public void transfer(String from, String to, double amount) {
String sql = "UPDATE account SET balance = balance + ? WHERE name = ?";
try (Connection conn = dataSource.getConnection()) {
conn.setAutoCommit(false); // 開啟事務
try (PreparedStatement ps = conn.prepareStatement(sql)) {
// 扣款
ps.setDouble(1, -amount);
ps.setString(2, from);
ps.executeUpdate();
// 入賬
ps.setDouble(1, amount);
ps.setString(2, to);
ps.executeUpdate();
conn.commit(); // 關鍵:提交事務
} catch (SQLException e) {
conn.rollback(); // 回滾
throw new RuntimeException("轉賬失敗", e);
}
} catch (SQLException e) {
throw new RuntimeException("數據庫連接失敗", e);
}
}
「已找到原因,字符打多了」——通常是SQL語句中多引號、少逗號、或參數順序錯位。
數據庫無變化 90% 是 **事務未提交** 或 **參數綁定錯誤**。「字符打多了」看似小錯,實則是SQL拼接不可控的典型證據。**堅持PreparedStatement + 顯式事務 + try-with-resources**,告別此類低級錯誤。