JDBC (Java Database Connectivity) 是 Java 應用與關聯式資料庫互動的標準 API。無論你使用 MyBatis、JPA/Hibernate 還是 Spring JdbcTemplate,底層皆建構於 JDBC 之上。掌握 JDBC 核心流程、資源管理與事務控制,是排查連線洩漏、SQL 注入、死鎖、效能瓶頸的前提。本文系統梳理 JDBC 完整操作步驟、最佳實踐與常見坑點。
| 介面 | 核心職責 | 常用實作 |
|---|---|---|
| Driver | 驅動註冊入口 | com.mysql.cj.jdbc.Driver |
| Connection | 會話上下文、事務邊界、Statement 工廠 | JDBC4Connection |
| Statement | 靜態 SQL 執行 | StatementImpl |
| PreparedStatement | 預編譯參數化 SQL,**防注入**、執行計劃複用 | PreparedStatementImpl |
| CallableStatement | 儲存過程/函數調用 (OUT/INOUT 參數) | CallableStatementImpl |
| ResultSet | 結果集游標、元數據、可滾動/可更新 | ResultSetImpl |
| DatabaseMetaData | 資料庫結構元數據 (表、欄位、索引、權限) | DatabaseMetaDataImpl |
| ParameterMetaData | 參數元數據 (類型、模式、精度) | ParameterMetaDataImpl |
// 1. 簡單 URL (含用戶密碼)
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db?user=root&password=123");
// 2. 獨立參數
Connection conn = DriverManager.getConnection(url, "root", "123");
// 3. Properties 物件 (適合動態屬性、連線池配置)
Properties props = new Properties();
props.setProperty("user", "root");
props.setProperty("password", "123");
props.setProperty("useSSL", "false");
Connection conn = DriverManager.getConnection(url, props);
String sql = "INSERT INTO users(username, email, age) VALUES (?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, "alice");
ps.setString(2, "alice@example.com");
ps.setInt(3, 25);
ps.executeUpdate();
}
conn.setAutoCommit(false); // 手動事務
try (PreparedStatement ps = conn.prepareStatement(sql)) {
for (User u : userList) {
ps.setString(1, u.getName());
ps.setString(2, u.getEmail());
ps.setInt(3, u.getAge());
ps.addBatch();
}
int[] counts = ps.executeBatch(); // 返回每條影響行數
conn.commit();
} catch (BatchUpdateException e) {
conn.rollback();
int[] updateCounts = e.getUpdateCounts(); // 部分成功分析
}
conn.setAutoCommit(false); // 開啟手動事務
try {
// ... 多條 SQL
conn.commit();
} catch (SQLException e) {
conn.rollback(); // 回滾
throw e;
} finally {
conn.setAutoCommit(true); // 恢復預設
}
| 級別 | 常量 | 髒讀 | 不可重複讀 | 幻讀 | 典型鎖 |
|---|---|---|---|---|---|
| READ_UNCOMMITTED | 1 | ✅ | ✅ | ✅ | 無共享鎖 |
| READ_COMMITTED | 2 | ❌ | ✅ | ✅ | 瞬間共享鎖 (RC) |
| REPEATABLE_READ | 4 | ❌ | ❌ | ✅ | 持有共享鎖 (RR) + Next-Key Lock |
| SERIALIZABLE | 8 | ❌ | ❌ | ❌ | 表鎖/範圍鎖 |
設定方式:`conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED)` (需在事務開始前)。
頻繁創建/銷毀物理連線極其昂貴。主流連線池:
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.idle-timeout=300000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.pool-name=MyAppPool
JDBC 雖屬底層 API,但其設計哲學 (介面隔離、驅動 SPI、事務邊界、資源管理) 深刻影響所有上層框架。熟練掌握 JDBC 核心流程、PreparedStatement 參數化、批次處理、事務隔離與連線池調優,是 Java 後端工程師從「會用框架」進階到「懂原理、能調優、會排查」的關鍵門檻。