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

JDBC 連接數據庫完整指南:從驅動加載到 CRUD 實戰

     編輯:Java 綜合教學

JDBC 核心機制與實戰總結

初學者常因「缺少驅動包」而被 JDBC 擋在門外。本文從 JDBC 與 JDBC Driver 的區別講起,逐步拆解連接建立、Statement 三大類型、ResultSet 遊標操作及連接池選型,助你避開踩坑陷阱。

一、JDBC vs JDBC Driver:規範與實現的分離

  • JDBC (Java Database Connectivity):JDK 定義的接口規範(java.sql.*、javax.sql.*),僅聲明 Connection、Statement、ResultSet 等接口,不提供實現。
  • JDBC Driver:具體數據庫廠商提供的實現類(如 MySQL 的 mysql-connector-java、Oracle 的 ojdbc),實現 JDBC 接口。

設計初衷:面向接口編程,切換數據庫只需換驅動包與連接串,業務代碼無需修改(OCP 原則)。

二、驅動安裝與加載

安裝方式

  1. 官網下載 JAR(如 mysql-connector-java-8.0.33.jar)
  2. 放入 Classpath:
    - Java SE:-cp 或 CLASSPATH 環境變量
    - Java EE:WEB-INF/lib 或 Maven/Gradle 依賴管理

驅動加載(JDBC 4.0+ 自動發現)

// JDBC 4.0 之前需顯式加載(現已罕用)
Class.forName("com.mysql.cj.jdbc.Driver");

// JDBC 4.0+ 只需確保 JAR 在 classpath,DriverManager 會自動發現 SPI

三、建立連接:DriverManager vs DataSource

DriverManager(簡單、適合測試/輕量級)

String url  = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";
String user = "root";
String pwd  = "123456";

// 方式 1:URL 包含憑證
Connection conn = DriverManager.getConnection(url);

// 方式 2:分離參數(推薦,可讀性強)
Connection conn = DriverManager.getConnection(url, user, pwd);

// 方式 3:Properties 傳遞更多屬性(字符編碼、連接超時等)
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", pwd);
props.setProperty("characterEncoding", "UTF-8");
Connection conn = DriverManager.getConnection(url, props);

DataSource(企業級標準、支援連接池)

主流實現:HikariCP(Spring Boot 2.x 默認)、Druid、DBCP2、C3P0。
優勢:連接複用、預編譯語句緩存、監控指標、優雅關閉。

四、Statement 三大類型與選型

接口創建方法特點適用場景
Statementconn.createStatement()靜態 SQL,無參數,易受注入攻擊極簡單、無參查詢、DDL
PreparedStatementconn.prepareStatement(sql)預編譯、參數化(?佔位符)、防注入、執行計劃緩存90%+ 業務查詢/更新
CallableStatementconn.prepareCall("{call proc(?,?)}")調用存儲過程/函數複雜邏輯下推數據庫

五、核心 CRUD 操作模板

查詢

String sql = "SELECT id, name, age FROM user WHERE age > ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    ps.setInt(1, 18);
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) { // 遊標前移
            long id   = rs.getLong("id");      // 推薦用列名,可讀性強
            String name = rs.getString("name");
            int age   = rs.getInt("age");
            // 處理行數據
        }
    }
}

增刪改

String sql = "INSERT INTO user(name, age) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
    ps.setString(1, "Alice");
    ps.setInt(2, 25);
    int rows = ps.executeUpdate(); // 返回影響行數
    // 獲取自增主鍵
    try (ResultSet keys = ps.getGeneratedKeys()) {
        if (keys.next()) System.out.println("新ID: " + keys.getLong(1));
    }
}

六、ResultSet 進階:可滾動與可更新


// 創建可滾動、只讀的 ResultSet
Statement stmt = conn.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE,  // 可前後移動
    ResultSet.CONCUR_READ_ONLY          // 唯讀
);
ResultSet rs = stmt.executeQuery("SELECT * FROM user");
rs.last();          // 跳到最後一行
rs.absolute(5);     // 跳到第 5 行
rs.relative(-2);    // 相對當前行向前 2 行

七、資源關閉與異常處理最佳實踐

  • JDK 7+ try-with-resources 自動關閉 Connection、Statement、ResultSet(實現 AutoCloseable)
  • 捕獲 SQLException 並轉換為業務異常,避免棧信息洩露
  • 生產環境禁用 DriverManager,必須使用連接池

八、常見坑點速查

  1. URL 寫錯:端口、數據庫名、時區參數(serverTimezone=UTC)
  2. 驅動版本不匹配:MySQL 8.0+ 驅動類名變為 com.mysql.cj.jdbc.Driver
  3. 字符編碼亂碼:URL 加 characterEncoding=UTF-8,表/庫建立時指定 utf8mb4
  4. Statement 注入風險:堅決不用字符串拼接 SQL,全量改用 PreparedStatement
  5. ResultSet 列索引從 1 開始:rs.getInt(1) 而非 0
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved