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

JDBC 核心操作完全手冊:連接、執行、結果處理、批量與事務

     編輯:Java 相關知識

標準 JDBC 操作四步走

  1. 獲取連接(Connection)
  2. 執行 SQL(Statement/PreparedStatement/CallableStatement)
  3. 處理結果(ResultSet/更新計數)
  4. 釋放資源(close() 逆序關閉)

1. 獲取數據庫連接

方式一:DriverManager(獨立應用)

String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL";
String user = "system", pwd = "manager";
Class.forName("oracle.jdbc.driver.OracleDriver"); // JDK 6+ 可省略
Connection conn = DriverManager.getConnection(url, user, pwd);

方式二:JNDI DataSource(Web 容器/連接池)

Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/myDB");
Connection conn = ds.getConnection(); // 從連接池獲取

生產環境強制使用連接池(HikariCP、Druid、DBCP2),禁止直接 DriverManager。

2. 執行 SQL 語句

介面適用場景關鍵方法
Statement靜態 SQL、無參數executeQuery()/executeUpdate()
PreparedStatement參數化 SQL、防注入、預編譯複用setXxx()、executeQuery/Update()
CallableStatement存儲過程/函數registerOutParameter()、execute()

PreparedStatement 參數化範例

String sql = "INSERT INTO users(id, name, email) VALUES (?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    ps.setLong(1, 1001L);
    ps.setString(2, "張三");
    ps.setString(3, "zhangsan@example.com");
    int rows = ps.executeUpdate();
}

3. 處理執行結果

  • 查詢:返回 ResultSet,游標初始在第一行之前,next() 逐行推進
  • 更新:返回 int 影響行數

ResultSet 常用導航與獲取

while (rs.next()) {
    long id = rs.getLong("id");           // 或 getLong(1)
    String name = rs.getString("name");
    Date created = rs.getTimestamp("created_at");
}
// 可滾動/可更新 ResultSet
Statement stmt = conn.createStatement(
    ResultSet.TYPE_SCROLL_INSENSITIVE,  // 可前後移動
    ResultSet.CONCUR_UPDATABLE          // 可更新
);
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
rs.absolute(5);        // 直接跳第 5 行
rs.updateString("name", "新名");
rs.updateRow();        // 寫回數據庫

4. 資源釋放鐵律:try-with-resources (JDK 7+)

try (Connection conn = ds.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql);
     ResultSet rs = ps.executeQuery()) {

    while (rs.next()) { /* ... */ }
} // 自動按逆序關閉 rs → ps → conn

舊代碼手動關閉順序:ResultSet → Statement → Connection,每個 close() 獨立 try-catch。

進階技巧:批量更新

Statement 批量(異構 SQL)

try (Statement stmt = conn.createStatement()) {
    stmt.addBatch("INSERT INTO log VALUES (1, 'A')");
    stmt.addBatch("UPDATE users SET cnt=cnt+1 WHERE id=1");
    stmt.addBatch("DELETE FROM temp WHERE id<100");
    int[] counts = stmt.executeBatch(); // 每條 SQL 影響行數
}

PreparedStatement 批量(同構 SQL、多組參數)

String sql = "INSERT INTO batch_demo(id, val) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    for (int i = 1; i <= 10000; i++) {
        ps.setInt(1, i);
        ps.setString(2, "val_" + i);
        ps.addBatch();
        if (i % 1000 == 0) ps.executeBatch(); // 分批提交防 OOM
    }
    ps.executeBatch(); // 剩餘
}

事務控制:ACID 落地

Connection conn = ds.getConnection();
try {
    conn.setAutoCommit(false); // 關閉自動提交

    // 業務邏輯:多條 SQL 組成原子操作
    try (PreparedStatement ps1 = conn.prepareStatement(sql1);
         PreparedStatement ps2 = conn.prepareStatement(sql2)) {
        ps1.executeUpdate();
        ps2.executeUpdate();
    }

    conn.commit(); // 全部成功提交
} catch (SQLException e) {
    conn.rollback(); // 任一失敗回滾
    throw e;
} finally {
    conn.setAutoCommit(true); // 恢復默認
    conn.close();
}

關鍵最佳實踐清單

  • ✅ 必須用 PreparedStatement:防 SQL 注入、預編譯複用、類型安全
  • ✅ 連接池配置合理:最大連接數、獲取超時、閒置回收、驗證查詢
  • ✅ 大數據量分頁用游標/流式讀取:setFetchSize()、ResultSet.TYPE_FORWARD_ONLY
  • ✅ 事務邊界清晰:業務方法層面控制,避免跨層傳遞 Connection
  • ✅ 異常不吞沒:記錄 SQL 狀態碼、錯誤碼、SQL 文本便於排查
  • ❌ 禁用 Statement 拼接參數
  • ❌ 禁止長事務:鎖競爭、連接泄漏、死鎖風險

常用數據庫 JDBC URL 速查

數據庫驅動類URL 範例
MySQL 8+com.mysql.cj.jdbc.Driverjdbc:mysql://host:3306/db?useSSL=false&serverTimezone=UTC
PostgreSQLorg.postgresql.Driverjdbc:postgresql://host:5432/db
Oracle 19coracle.jdbc.OracleDriverjdbc:oracle:thin:@//host:1521/service_name
SQL Servercom.microsoft.sqlserver.jdbc.SQLServerDriverjdbc:sqlserver://host:1433;databaseName=db;encrypt=true
H2 (嵌入式)org.h2.Driverjdbc:h2:~/test;AUTO_SERVER=TRUE

JDBC 是 Java 數據訪問的基石,掌握其核心模式與最佳實踐,是從「會用」走向「用好」的關鍵。

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