首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

JDBC 資料庫連接技術完整入門:驅動載入、連線池、PreparedStatement、事務控制與最佳實踐

     編輯:Java 綜合教學

前言

JDBC (Java Database Connectivity) 是 Java 存取關聯式資料庫的標準 API。本文從基礎步驟進階到生產級最佳實踐,涵蓋驅動載入、連線管理、SQL 執行、結果處理、資源釋放、連線池、事務與防注入。

JDBC 核心 API 概覽

介面/類別套件職責
DriverManagerjava.sql管理 JDBC 驅動、建立連線 (簡單應用)
DataSourcejavax.sql連線池介面,生產環境標準取得連線方式
Connectionjava.sql資料庫會話、事務控制、建立 Statement
Statementjava.sql執行靜態 SQL
PreparedStatementjava.sql預編譯 SQL、參數綁定、**防 SQL 注入**
CallableStatementjava.sql呼叫預存程序
ResultSetjava.sql查詢結果集游標
SQLExceptionjava.sql資料庫操作異常

基礎六步驟 (DriverManager 版)

public class JdbcBasicDemo {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/pet?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Taipei";
        String user = "root";
        String password = "123456";

        // 1. 載入驅動 (JDBC 4.0+ SPI 機制可省略,但建議保留相容)
        try { Class.forName("com.mysql.cj.jdbc.Driver"); } 
        catch (ClassNotFoundException e) { throw new RuntimeException("找不到驅動", e); }

        // 2-6. try-with-resources 自動關閉資源 (JDK 7+)
        try (Connection conn = DriverManager.getConnection(url, user, password);
             PreparedStatement ps = conn.prepareStatement("SELECT COUNT(1) AS cnt FROM users WHERE username=? AND userpwd=?")) {

            // 3. 設定參數
            ps.setString(1, "admin");
            ps.setString(2, "123456");

            // 4. 執行查詢
            try (ResultSet rs = ps.executeQuery()) {
                // 5. 處理結果
                if (rs.next()) {
                    int count = rs.getInt("cnt");
                    System.out.println(count == 1 ? "登入成功" : "登入失敗");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        // 6. 連線自動關閉 (try-with-resources)
    }
}

進階:連線池 (DataSource) - 生產環境必備

HikariCP (Spring Boot 2.x+ 預設、效能最強)

// Maven

    com.zaxxer
    HikariCP
    5.0.1


// 配置 (application.yml)
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/pet?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Taipei
    username: root
    password: 123456
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      connection-test-query: SELECT 1

手動建立 HikariDataSource (非 Spring 環境)

HikariConfig config = new HikariConfig();
config.setJdbcUrl(url);
config.setUsername(user);
config.setPassword(password);
config.setMaximumPoolSize(20);
DataSource ds = new HikariDataSource(config);

// 使用
try (Connection conn = ds.getConnection(); ...) { ... }

關鍵最佳實踐總結

實踐錯誤寫法正確寫法理由
參數化查詢`"SELECT * FROM t WHERE name='" + name + "'"``PreparedStatement` + `setString`防 SQL 注入、預編譯重用執行計畫
資源釋放手動 close、漏關閉try-with-resources (JDK 7+)保證釋放、程式碼簡潔
事務控制自動提交、業務中間拋異常不回滾`conn.setAutoCommit(false)` + `commit`/`rollback`保證 ACID
批次處理迴圈逐筆 executeUpdate`addBatch()` + `executeBatch()`減少網路往返、提升 10x+ 效能
大資料查詢一次性載入所有 ResultSet`setFetchSize(1000)` + 游標逐行處理避免 OOM、記憶體恆定
連線獲取每次 `DriverManager.getConnection`連線池 `DataSource.getConnection()`重用連線、控制併發、監控指標

事務控制範例

public void transfer(String from, String to, double amount) throws SQLException {
    try (Connection conn = ds.getConnection()) {
        conn.setAutoCommit(false); // 開啟事務
        try (PreparedStatement dec = conn.prepareStatement("UPDATE account SET balance=balance-? WHERE user=?");
             PreparedStatement inc = conn.prepareStatement("UPDATE account SET balance=balance+? WHERE user=?")) {

            dec.setDouble(1, amount); dec.setString(2, from);
            inc.setDouble(1, amount); inc.setString(2, to);

            int decRows = dec.executeUpdate();
            int incRows = inc.executeUpdate();

            if (decRows == 1 && incRows == 1) {
                conn.commit(); // 提交
            } else {
                conn.rollback(); // 回滾
                throw new SQLException("轉帳失敗:扣款或入帳行數異常");
            }
        } catch (SQLException e) {
            conn.rollback();
            throw e;
        }
    }
}

常見錯誤與排查

錯誤原因解決
ClassNotFoundException: DriverJDBC 驅動 JAR 未在 classpathMaven 引入對應驅動 (mysql-connector-j, postgresql, ojdbc11 等)
Communications link failure網路不通、資料庫未啟動、防火牆、URL 錯誤檢查 host/port、ping、telnet、資料庫狀態、防火牆規則
Public Key Retrieval is not allowedMySQL 8.0+ 預設需 SSLURL 加 `allowPublicKeyRetrieval=true&useSSL=false` (開發環境)
Connection refused / Timeout連線池耗盡、資料庫 max_connections 達上限調大連線池、檢查洩漏、優化慢查詢、啟用連線洩漏偵測
ResultSet is closedStatement/Connection 關閉後仍操作 ResultSet在 try-with-resources 區塊內處理完畢

結語

JDBC 雖是底層 API,但**連線池 + PreparedStatement + try-with-resources + 事務邊界** 四大核心實踐構成了穩健資料存取的基石。現代專案建議直接使用 **Spring JDBC (JdbcTemplate/NamedParameterJdbcTemplate)** 或 **MyBatis/JOOQ** 進一步簡化樣板代碼,但理解 JDBC 底層機制對排查疑難雜症、效能調優至關重要。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved