所有 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;
關鍵點:
Class.forName() 可省略。characterEncoding=utf-8 避免中文亂碼。Statement stmt = conn.createStatement();
String sql = "DELETE FROM diary WHERE title = '" + title + "'";
int count = stmt.executeUpdate(sql); // 返回影響行數
System.out.println("刪除成功,影響行數:" + count);
⚠️ 風險:字串拼接極易導致 SQL 注入,嚴禁用於含用戶輸入的場景。
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
優勢:
setInt、setDate 等強類型方法避免隱式轉換錯誤。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("資料庫資源已釋放");
}
最佳實踐:
AutoCloseable 接口)。conn.close() 實為歸還連線而非物理關閉。將上述四階段封裝為 DBUtil:
getConnection():從連線池獲取executeQuery(sql, params, rowMapper):通用查詢executeUpdate(sql, params):通用增刪改closeAll(rs, stmt, conn):統一釋放規範流程、封裝細節,讓 JDBC 代碼既安全又優雅。