首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

JDBC 操作資料庫四大核心流程詳解:從連線到資源釋放的最佳實踐

     編輯:MySQL 資料庫相關知識

所有 JDBC 應用程式都遵循同一核心流程:載入驅動 → 建立連線 → 執行 SQL → 處理結果 → 釋放資源。本文深度拆解每個階段的關鍵 API、異常處理與資源管理最佳實踐,並提供可復用的工具類設計思路。

階段一:載入驅動與建立連線

String driverName = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://10.5.110.239:3306/test?" 
           + "user=root&password=chen&characterEncoding=utf-8";
Connection conn = null;

try {
    Class.forName(driverName);                    // 1. 載入驅動類
    conn = DriverManager.getConnection(url);      // 2. 建立連線
    System.out.println("資料庫連線成功");
} catch (ClassNotFoundException e) {
    e.printStackTrace();  // 驅動 Jar 包缺失或類名錯誤
} catch (SQLException e) {
    e.printStackTrace();  // URL 錯誤、網路不通、認證失敗
}
return conn;

關鍵點:

  • JDBC 4.0+ (Java 6+) 支援 SPI 自動載入驅動,Class.forName() 可省略。
  • 連線字串建議包含 characterEncoding=utf-8 避免中文亂碼。
  • 生產環境必須使用連線池(HikariCP、Druid),不可頻繁開關物理連線。

階段二:執行 SQL — Statement vs PreparedStatement

Statement:適合一次性、固定 SQL

Statement stmt = conn.createStatement();
String sql = "DELETE FROM diary WHERE title = '" + title + "'";
int count = stmt.executeUpdate(sql);  // 返回影響行數
System.out.println("刪除成功,影響行數:" + count);

⚠️ 風險:字串拼接極易導致 SQL 注入,嚴禁用於含用戶輸入的場景。

PreparedStatement:參數化查詢,防注入、可重用、效能更優

String sql = "INSERT INTO diary(title, content, authorname, time) VALUES(?, ?, ?, NOW())";
PreparedStatement pstmt = conn.prepareStatement(sql);

pstmt.setString(1, diary.getTitle());
pstmt.setString(2, diary.getContent());
pstmt.setString(3, diary.getAuthorName());

int count = pstmt.executeUpdate();  // 執行 DML
// int count = pstmt.executeQuery(); // 執行 SELECT 返回 ResultSet

優勢:

  • 預編譯:DB 端解析、優化、生成執行計劃僅一次,重複執行極快。
  • 參數綁定:徹底杜絕 SQL 注入。
  • 類型安全:setInt、setDate 等強類型方法避免隱式轉換錯誤。

階段三:處理結果集 ResultSet

ResultSet rs = stmt.executeQuery("SELECT id, title, content, authorname, time FROM diary");
while (rs.next()) {  // 游標下移,無下一行返回 false
    Diary d = new Diary();
    d.setId(rs.getInt("id"));
    d.setTitle(rs.getString("title"));
    d.setContent(rs.getString("content"));
    d.setAuthorName(rs.getString("authorname"));
    d.setTime(rs.getTimestamp("time"));
    list.add(d);
}

注意:

  • executeQuery 用於 SELECT,返回 ResultSet;executeUpdate 用於 DML/DDL,返回影響行數。
  • 列名建議使用別名(AS)避免多表查詢列名衝突。
  • 大數據量時考慮 setFetchSize() 分批抓取,避免 OOM。

階段四:資源釋放 — 逆序關閉,防洩漏

public static void close(ResultSet rs, Statement stmt, Connection conn) {
    try { if (rs != null) rs.close(); } catch (SQLException e) { e.printStackTrace(); }
    try { if (stmt != null) stmt.close(); } catch (SQLException e) { e.printStackTrace(); }
    try { if (conn != null && !conn.isClosed()) conn.close(); } catch (SQLException e) { e.printStackTrace(); }
    System.out.println("資料庫資源已釋放");
}

最佳實踐:

  • Java 7+ 使用 try-with-resources 自動關閉(實現 AutoCloseable 接口)。
  • 連線池場景下,conn.close() 實為歸還連線而非物理關閉。
  • 異常處理不可吞噬,至少記錄日誌。

工具類封裝建議

將上述四階段封裝為 DBUtil:

  • getConnection():從連線池獲取
  • executeQuery(sql, params, rowMapper):通用查詢
  • executeUpdate(sql, params):通用增刪改
  • closeAll(rs, stmt, conn):統一釋放

規範流程、封裝細節,讓 JDBC 代碼既安全又優雅。

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