JDBC (Java Database Connectivity) 是 Java 應用程式存取關聯式資料庫的標準 API。設計目標:提供**統一介面**、**資料庫獨立性**、**支援基本 SQL 功能**、建立在既有標準 (X/Open SQL CLI / ODBC) 之上、保持簡單與強型別。本文系統整理 JDBC 架構、核心介面、驅動類型、使用情境與安全性考量。
┌─────────────────────────────────────┐
│ 應用程式 (Application) │
│ 使用 java.sql.* 介面 (JDBC API) │
├─────────────────────────────────────┤
│ DriverManager │ ← 驅動管理、連線取得
├─────────────────────────────────────┤
│ JDBC Driver 介面 (SPI) │ ← 廠商實作
│ Connection, Statement, │
│ PreparedStatement, CallableStatement,│
│ ResultSet, DatabaseMetaData, ... │
├─────────────────────────────────────┤
│ 資料庫 (DBMS) │
└─────────────────────────────────────┘
| 介面 | 職責 | 關鍵方法 |
|---|---|---|
DriverManager | 驅動註冊、連線取得 | getConnection(url, props), registerDriver() |
Connection | 資料庫會話、交易控制、元資料 | createStatement(), prepareStatement(), commit/rollback(), getMetaData() |
Statement | 執行靜態 SQL | executeQuery(), executeUpdate(), execute() |
PreparedStatement | 預編譯參數化 SQL (防注入、效能) | setXxx(index, val), executeUpdate/query() |
CallableStatement | 呼叫預存程序 (OUT/INOUT 參數) | registerOutParameter(), getXxx(index) |
ResultSet | 結果集游標導航與資料提取 | next(), getXxx(colIndex/Name), absolute(), updateXxx() |
DatabaseMetaData | 資料庫結構、能力、版本資訊 | getTables(), getColumns(), supportsTransactions() |
ResultSetMetaData | 結果集欄位資訊 | getColumnCount(), getColumnLabel(), getColumnType() |
| 類型 | 名稱 | 架構 | 優點 | 缺點 |
|---|---|---|---|---|
| Type 1 | JDBC-ODBC Bridge | JDBC → ODBC → DBMS | 支援所有有 ODBC 驅動的 DB | 需客戶端安裝 ODBC、效能差、JDK 8 移除 |
| Type 2 | Native-API | JDBC → Native Client Lib → DBMS | 比 Type 1 快 | 需安裝 Native Library、可攜性差 |
| Type 3 | Network Protocol | JDBC → Middleware Server → DBMS | 純 Java 客戶端、支援多種 DB | 中介層複雜、效能有額外開銷 |
| Type 4 | Thin / Pure Java | JDBC → DBMS Native Protocol (TCP) | 純 Java、無安裝、效能最佳、標準選擇 | 各 DB 需專屬驅動 |
現代標準:Type 4 (如 MySQL Connector/J, PostgreSQL JDBC, Oracle JDBC Thin, Microsoft JDBC Driver for SQL Server)。
// 1. 載入驅動 (JDBC 4.0+ SPI 自動載入,可省略)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 建立連線
String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url, "user", "pass");
// 3. 建立 Statement
try (Statement stmt = conn.createStatement()) {
// 4. 執行查詢
try (ResultSet rs = stmt.executeQuery("SELECT id, name FROM users")) {
// 5. 處理結果
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
}
} // 自動關閉 stmt, rs
// 6. 關閉連線 (或交由連線池管理)
conn.close();
String sql = "SELECT * FROM users WHERE email = ? AND status = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, email);
ps.setInt(2, 1);
try (ResultSet rs = ps.executeQuery()) { /* ... */ }
}
優點:防 SQL 注入、查詢計畫重用、型別安全、可讀性。
conn.setAutoCommit(false);
try {
// 多條更新...
conn.commit();
} catch (SQLException e) {
conn.rollback();
throw e;
} finally {
conn.setAutoCommit(true);
}
BLOB:ps.setBinaryStream(), rs.getBinaryStream()CLOB:ps.setCharacterStream(), rs.getCharacterStream()| 情境 | 特徵 | 安全考量 |
|---|---|---|
| Applet (舊) | 瀏覽器沙箱、不可信 | 限制本地檔案/網路存取、只能連回來源主機 |
| Application | 本地信任程式碼 | 完整檔案/網路存取權限 |
| Trusted Applet | 簽名驗證通過 | 等同 Application 權限 |
| 三層架構 | Client → Middle Tier → DB | 中介層集中授權、連線池、稽核 |
SecurityManager.checkConnect(host, port)checkRead/write()DatabaseMetaData meta = conn.getMetaData();
System.out.println("DB: " + meta.getDatabaseProductName() + " " + meta.getDatabaseProductVersion());
System.out.println("Driver: " + meta.getDriverName() + " " + meta.getDriverVersion());
// 列出所有表
try (ResultSet tables = meta.getTables(null, null, "%", new String[]{"TABLE"})) {
while (tables.next()) {
System.out.println(tables.getString("TABLE_NAME"));
}
}
try-with-resources、getObject(Class<T>)、LocalDate/LocalDateTime 直接對應、executeLargeUpdate()。ps.addBatch() + executeBatch() 大量寫入優化。JDBC 是 Java 資料存取的基石。掌握核心介面、驅動類型、連線池、交易控制、參數化查詢與安全性模型,是建構健壯、高效、安全資料庫應用的前提。現代開發多透過 Spring JDBC、MyBatis、JOOQ 等框架封裝 JDBC,但理解底層運作機制仍是排查效能問題、解決資料一致性 Bug、設計高併發架構的關鍵能力。