JDBC 連線流程極其精簡,但細節決定成敗。本篇深入剖析每一步的機制、寫法演進與最佳實踐。
// MySQL 範例
Class.forName("com.mysql.cj.jdbc.Driver").newInstance();
// Oracle 範例
Class.forName("oracle.jdbc.driver.OracleDriver");
// PostgreSQL 範例
Class.forName("org.postgresql.Driver");
// SQL Server 範例
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Class.forName() 觸發類別載入,靜態區塊中驅動類別會向 DriverManager 註冊自身。.newInstance() 確保實例化(舊版驅動需要)。
驅動 JAR 的 META-INF/services/java.sql.Driver 檔案列出實作類別,DriverManager 初始化時透過 ServiceLoader 自動發現並註冊。
// 直接取得連線,無需顯式 Class.forName
Connection conn = DriverManager.getConnection(url, user, pass);
建議:保留 Class.forName() 可提早發現驅動遺漏(啟動時拋出異常),而非首次連線時才失敗。
Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
jdbc::
jdbc:固定協定前綴subprotocol:驅動識別碼(如 mysql、postgresql、oracle)subname:資料庫定位資訊(主機、埠、資料庫名、參數)| 資料庫 | URL 範例 | 關鍵參數 |
|---|---|---|
| MySQL | jdbc:mysql://localhost:3306/mydb?serverTimezone=Asia/Taipei&useSSL=false&allowPublicKeyRetrieval=true | 時區、SSL、公開金鑰擷取 |
| PostgreSQL | jdbc:postgresql://localhost:5432/mydb?currentSchema=public | Schema 設定 |
| Oracle (Thin) | jdbc:oracle:thin:@//localhost:1521/ORCLPDB1 | Easy Connect 語法 |
| Oracle (SID) | jdbc:oracle:thin:@localhost:1521:ORCL | 傳統 SID 語法 |
| SQL Server | jdbc:sqlserver://localhost:1433;databaseName=mydb;encrypt=true;trustServerCertificate=true | 加密、信任憑證 |
| H2 (檔案) | jdbc:h2:file:./data/mydb;AUTO_SERVER=TRUE | 嵌入式、多連線 |
| H2 (記憶體) | jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 | 測試專用 |
Properties props = new Properties();
props.setProperty("user", "admin");
props.setProperty("password", "secret");
props.setProperty("characterEncoding", "UTF-8");
props.setProperty("useUnicode", "true");
props.setProperty("autoReconnect", "true");
props.setProperty("connectTimeout", "5000");
props.setProperty("socketTimeout", "30000");
Connection conn = DriverManager.getConnection(jdbcUrl, props);
此方式支援更多進階屬性,程式碼可讀性較高。
DriverManager 維護已註冊驅動清單。呼叫 getConnection 時:
connect(url, props) 方法Connection 的驅動獲勝SQLException: No suitable driver found因此 URL 格式必須精確匹配目標驅動的預期模式。
// 正確模式:try-with-resources (JDK 7+)
try (Connection conn = DriverManager.getConnection(url, props)) {
// 使用連線
// 區塊結束自動關閉,即使拋出異常
} catch (SQLException e) {
// 錯誤處理
}
嚴禁:長期持有連線不關閉、靜態變數儲存連線、跨執行緒共用單一連線(非執行緒安全)。
| 錯誤現象 | 原因 | 解決 |
|---|---|---|
| No suitable driver found for jdbc:mysql://... | 驅動未載入、URL 拼寫錯誤 | 檢查依賴、驗證 URL 格式 |
| Access denied for user 'root'@'localhost' | 帳密錯誤、權限不足、主機不符 | 確認用戶存在、GRANT 權限、FLUSH PRIVILEGES |
| Communications link failure | 網路不通、防火牆、MySQL 關閉、埠錯誤 | ping/telnet 測試、檢查 bind-address=0.0.0.0 |
| Server timezone value '...' is unrecognized | 時區 ID 不相容 | URL 加 serverTimezone=Asia/Taipei |
| Public Key Retrieval is not allowed | MySQL 8 caching_sha2_password | URL 加 allowPublicKeyRetrieval=true 或改用 native password |
生產環境絕不直接使用 DriverManager 逐條建立連線。下一階段將介紹:
掌握驅動載入機制與 URL 結構,是 JDBC 開發的基石。現代框架(Spring Data、MyBatis、JOOQ)底層皆建立在此機制之上,理解原理有助於排查疑難雜症與效能調優。