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

JDBC 核心操作全攻略:連線、CRUD、批次、事務與進階 ResultSet

     編輯:Java 相關知識

標準 JDBC 操作流程

  1. 載入驅動:Class.forName("com.mysql.cj.jdbc.Driver") (JDBC 4.0+ 可省略)
  2. 建立連線:DriverManager.getConnection(url, user, pass) 或 JNDI DataSource
  3. 創建 Statement / PreparedStatement
  4. 執行 SQL:executeQuery (查詢) / executeUpdate (增刪改)
  5. 處理 ResultSet
  6. 關閉資源:ResultSet → Statement → Connection(逆序,try-with-resources 最佳)

兩種連線獲取方式

1. DriverManager (獨立應用、測試)

String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
String user = "root", pass = "123456";
try (Connection conn = DriverManager.getConnection(url, user, pass)) {
    // 使用連線
}

2. JNDI DataSource (Web 容器、生產環境)

// web.xml / context.xml 配置資料源
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/mydb");
try (Connection conn = ds.getConnection()) {
    // 連線池管理、事務整合更優
}

Statement vs PreparedStatement

特性StatementPreparedStatement
SQL 注入防護無,需手動轉義參數化查詢,原生防注入
效能每次編譯預編譯,批次執行極快
適用場景靜態 SQL、DDL業務 CRUD、動態條件、批次操作

原則:業務代碼**永遠使用 PreparedStatement**。

ResultSet 進階:可捲動、可更新


// 建立可捲動、可更新 ResultSet
try (Statement stmt = conn.createStatement(
        ResultSet.TYPE_SCROLL_INSENSITIVE,
        ResultSet.CONCUR_UPDATABLE);
     ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {

    rs.absolute(5);        // 直接跳第 5 行
    rs.previous();         // 上一行
    rs.updateString("name", "新名稱");
    rs.updateRow();        // 寫回資料庫
    rs.insertRow();        // 插入新行
    rs.deleteRow();        // 刪除當前行
}

注意:需資料庫驅動支援,主鍵無 NULL,且查詢需包含主鍵欄位。

批次更新:大幅提升寫入吞吐

1. Statement 批次 (異構 SQL)

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

2. PreparedStatement 批次 (同構 SQL,參數化)

String sql = "INSERT INTO user(name, email) VALUES (?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    for (User u : userList) {
        ps.setString(1, u.getName());
        ps.setString(2, u.getEmail());
        ps.addBatch();
        // 每 1000 條執行一次,防 OOM
        if (++count % 1000 == 0) ps.executeBatch();
    }
    ps.executeBatch(); // 剩餘
}

關鍵優化:MySQL 需 URL 附加 rewriteBatchedStatements=true 才能真正批次執行,否則退化為單條循環。

事務控制:ACID 落地

Connection conn = null;
try {
    conn = ds.getConnection();
    conn.setAutoCommit(false); // 開啟事務

    try (PreparedStatement ps1 = conn.prepareStatement(sql1);
         PreparedStatement ps2 = conn.prepareStatement(sql2)) {
        // 業務邏輯
        ps1.executeUpdate();
        ps2.executeUpdate();
    }

    conn.commit(); // 提交
} catch (Exception e) {
    if (conn != null) conn.rollback(); // 回滾
    throw e;
} finally {
    if (conn != null) {
        conn.setAutoCommit(true); // 恢復預設
        conn.close();
    }
}

最佳實踐:使用 Spring @Transactional 或 JTA 容器事務,避免手動管理錯誤。

資源關閉鐵律

// Java 7+ 標準寫法
try (Connection conn = ds.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql);
     ResultSet rs = ps.executeQuery()) {
    // 邏輯
} // 自動按逆序關閉 rs → ps → conn

總結

JDBC 雖屬基礎,但「連線池選擇、PreparedStatement 堅持、批次重寫優化、事務邊界清晰、資源自動關閉」五大鐵律,是區分新手與資深工程師的分水嶺。掌握這些,再配合 MyBatis/JdbcTemplate 等框架,才能寫出高性能、穩健的數據訪問層。

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