本文提供一個完整的 JDBC 連線工具類 connDB,示範 MySQL 環境下的核心功能:
PreparedStatement 參數綁定(防 SQL 注入)addBatch() / executeBatch())setAutoCommit(false)、commit()、rollback())package com.chinacountry.databases;
import java.sql.*;
import java.util.StringTokenizer;
public class connDB {
// 連線參數
private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver"; // MySQL 8.0+ 驅動類
private static final String CONN_URL = "jdbc:mysql://10.100.27.13:3306/db1?useSSL=false&serverTimezone=UTC";
private static final String USER = "naxweb";
private static final String PASSWORD = "naxweb";
private Connection conn = null;
private boolean autoCommit = true;
// 單例模式
private connDB() { init(); }
private void init() {
try {
Class.forName(DB_DRIVER).newInstance();
conn = DriverManager.getConnection(CONN_URL, USER, PASSWORD);
} catch (Exception e) {
System.err.println("connDB init error: " + e.getMessage());
e.printStackTrace();
}
}
public static connDB getInstance() {
return new connDB();
}
// 取得 PreparedStatement(支援參數綁定)
public PreparedStatement getPreparedStmt(String sql) throws SQLException {
if (conn == null || conn.isClosed()) init();
return conn.prepareStatement(sql);
}
// 批次處理範例
public void batchInsertExample() {
String sql = "INSERT INTO test_table (name, age) VALUES (?, ?)";
try (PreparedStatement pstmt = getPreparedStmt(sql)) {
conn.setAutoCommit(false); // 開啟交易
for (int i = 1; i <= 1000; i++) {
pstmt.setString(1, "User" + i);
pstmt.setInt(2, 20 + (i % 50));
pstmt.addBatch();
if (i % 100 == 0) pstmt.executeBatch(); // 分批提交,避免記憶體溢位
}
pstmt.executeBatch(); // 提交剩餘
conn.commit(); // 交易提交
} catch (SQLException e) {
try { if (conn != null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); }
e.printStackTrace();
} finally {
try { if (conn != null) conn.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); }
}
}
// 交易控制範例:轉帳
public boolean transfer(String fromAcct, String toAcct, double amount) {
String sql1 = "UPDATE account SET balance = balance - ? WHERE id = ?";
String sql2 = "UPDATE account SET balance = balance + ? WHERE id = ?";
try (PreparedStatement pstmt1 = getPreparedStmt(sql1);
PreparedStatement pstmt2 = getPreparedStmt(sql2)) {
conn.setAutoCommit(false);
pstmt1.setDouble(1, amount); pstmt1.setString(2, fromAcct);
pstmt2.setDouble(1, amount); pstmt2.setString(2, toAcct);
int r1 = pstmt1.executeUpdate();
int r2 = pstmt2.executeUpdate();
if (r1 == 1 && r2 == 1) {
conn.commit();
return true;
} else {
conn.rollback();
return false;
}
} catch (SQLException e) {
try { if (conn != null) conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); }
e.printStackTrace();
return false;
} finally {
try { if (conn != null) conn.setAutoCommit(true); } catch (SQLException e) { e.printStackTrace(); }
}
}
// 關閉連線
public void close() {
try { if (conn != null && !conn.isClosed()) conn.close(); } catch (SQLException e) { e.printStackTrace(); }
}
}
| 功能 | 關鍵 API | 注意事項 |
|---|---|---|
| 參數綁定 | pstmt.setXxx(index, value) | 索引從 1 開始;防 SQL 注入、自動處理資料型別轉換 |
| 批次處理 | addBatch()、executeBatch() | 大量資料分批提交(如每 1000 筆);配合 rewriteBatchedStatements=true 連線參數效能最佳 |
| 交易控制 | setAutoCommit(false)、commit()、rollback() | 務必在 finally 中恢復 autoCommit=true;捕捉異常時回滾 |
| 資源釋放 | try-with-resources (Java 7+) | Connection、Statement、ResultSet 皆實作 AutoCloseable |
jdbc:mysql://host:3306/db?useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=250&prepStmtCacheSqlLimit=2048
rewriteBatchedStatements=true:將批次 INSERT 重寫為多值 INSERT,效能提升 10 倍以上。cachePrepStmts 相關參數:啟用客戶端 PreparedStatement 快取。掌握 PreparedStatement、批次處理與交易控制是 Java 開發者操作資料庫的基本功。善用連線池(如 HikariCP)可進一步提升生產環境效能與穩定性。