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

Java 核心技術:JDBC 資料庫連線與操作完整指南

     編輯:Java 相關知識

雖然現代企業開發普遍採用 Hibernate、MyBatis 等 ORM 框架簡化資料存取,但 JDBC(Java Database Connectivity)作為 Java 操作關聯式資料庫的基石,深入理解其運作機制對於排查效能瓶頸、掌握底層資料流轉至關重要。本文將系統梳理 JDBC 核心流程、核心物件、進階特性與最佳實踐,助你建立扎實的資料庫程式設計基礎。

一、JDBC 核心操作流程

JDBC 操作資料庫遵循標準化的四步驟:

  1. 載入驅動程式:透過 Class.forName() 載入特定資料庫的 JDBC 驅動類別。
  2. 建立連線:使用 DriverManager.getConnection(url, user, password) 取得 Connection 物件。
  3. 執行 SQL 指令:透過 Statement、PreparedStatement 或 CallableStatement 發送 CRUD 操作。
  4. 處理結果集:使用 ResultSet 遍歷查詢結果,或獲取更新影響的行數。

最後務必在 finally 區塊中關閉 ResultSet、Statement、Connection,避免資源洩漏。

二、核心 API 物件詳解

物件用途
DriverManager管理驅動程式,建立資料庫連線
Connection代表與資料庫的會話,支援事務控制
Statement執行靜態 SQL 語句
PreparedStatement預編譯 SQL,防注入、提升效能
CallableStatement呼叫預存程序
ResultSet封裝查詢結果集,支援游標移動
Savepoint事務中設定回滾點

三、資料庫連線建立與驅動自動載入

3.1 傳統兩步驟連線

String driver = "com.mysql.cj.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, "root", "password");

3.2 JDBC 4.0+ 服務提供者機制(SPI)自動載入

將驅動完整類名寫入 META-INF/services/java.sql.Driver 檔案,置於 classpath 中,即可省略 Class.forName()。切換資料庫時僅需修改此檔案內容與對應 JAR 包。

四、CRUD 基礎操作範例

以下以 MySQL 為例,展示增刪改查完整流程:

try (Connection conn = DriverManager.getConnection(url, user, pwd);
     Statement stmt = conn.createStatement()) {
    // 新增
    stmt.executeUpdate("INSERT INTO user(id,name) VALUES(1,'張三')");
    // 查詢
    try (ResultSet rs = stmt.executeQuery("SELECT id,name FROM user")) {
        while (rs.next()) {
            System.out.println(rs.getInt("id") + " - " + rs.getString("name"));
        }
    }
    // 修改
    stmt.executeUpdate("UPDATE user SET name='李四' WHERE id=1");
    // 刪除
    stmt.executeUpdate("DELETE FROM user WHERE id=1");
}

五、預存程序呼叫

5.1 無參數預存程序

CallableStatement cstmt = conn.prepareCall("{call GetUser()}");
ResultSet rs = cstmt.executeQuery();

5.2 帶 IN/OUT 參數

// IN 參數
cstmt = conn.prepareCall("{call GetUserByID(?)}");
cstmt.setInt(1, 10);

// OUT 參數
cstmt.registerOutParameter(2, Types.VARCHAR);
cstmt.execute();
String outVal = cstmt.getString(2);

六、中繼資料獲取

6.1 資料庫中繼資料

DatabaseMetaData dbmd = conn.getMetaData();
System.out.println(dbmd.getDatabaseProductName() + " " + dbmd.getDatabaseProductVersion());
ResultSet tables = dbmd.getTables(null, null, "%", new String[]{"TABLE"});
while (tables.next()) {
    System.out.println(tables.getString("TABLE_NAME"));
}

6.2 結果集中繼資料

ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
    System.out.println(rsmd.getColumnName(i) + " : " + rsmd.getColumnTypeName(i));
}

七、可捲動與可更新的 ResultSet

建立 Statement 時指定型別與並發模式:

Statement stmt = conn.createStatement(
    ResultSet.TYPE_SCROLL_SENSITIVE,
    ResultSet.CONCUR_UPDATABLE);

支援操作:

  • rs.last() / rs.first() / rs.absolute(n) 移動游標
  • rs.moveToInsertRow() 移至插入行
  • rs.updateXxx(col, val) 修改欄位值
  • rs.insertRow() / rs.updateRow() / rs.deleteRow() 提交變更

八、預處理與批次處理

8.1 PreparedStatement 預編譯

SQL 模板預編譯,參數化查詢防注入,資料庫端緩存執行計畫:

PreparedStatement pst = conn.prepareStatement("INSERT INTO user(id,name) VALUES(?,?)");
pst.setInt(1, 100);
pst.setString(2, "王五");
pst.executeUpdate();

8.2 Statement 批次執行

Statement stmt = conn.createStatement();
stmt.addBatch("INSERT INTO user VALUES(1,'A')");
stmt.addBatch("INSERT INTO user VALUES(2,'B')");
stmt.executeBatch();

8.3 PreparedStatement + 批次(最佳效能)

PreparedStatement pst = conn.prepareStatement("INSERT INTO user(id,name) VALUES(?,?)");
for (int i = 0; i < 1000; i++) {
    pst.setInt(1, i);
    pst.setString(2, "User" + i);
    pst.addBatch();
}
pst.executeBatch();

九、事務控制與 Savepoint

9.1 基本事務

conn.setAutoCommit(false);
try {
    stmt.executeUpdate("INSERT INTO account VALUES(1,100)");
    stmt.executeUpdate("UPDATE account SET balance=balance-50 WHERE id=1");
    conn.commit();
} catch (Exception e) {
    conn.rollback();
} finally {
    conn.setAutoCommit(true);
}

9.2 Savepoint 部分回滾

Savepoint sp = conn.setSavepoint("SP1");
stmt.executeUpdate("INSERT INTO log VALUES(1,'step1')");
stmt.executeUpdate("INSERT INTO log VALUES(2,'step2')");
conn.rollback(sp); // 僅回滾到 SP1 之後的操作
conn.commit();

十、最佳實踐總結

  1. 優先使用 PreparedStatement 防止 SQL 注入並複用執行計畫。
  2. 大量資料操作採用批次處理,減少網路往返。
  3. 連線、Statement、ResultSet 必須在 try-with-resources 或 finally 中關閉。
  4. 合理設定事務隔離級別與自動提交模式。
  5. 生產環境建議使用連線池(HikariCP、Druid)管理連線生命週期。

掌握 JDBC 核心機制,不僅能在無框架環境下游刃有餘,更能在使用 ORM 時深入理解其底層行為,快速定位效能與資料一致性問題。

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