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

JDBC 事務控制核心:setAutoCommit、commit、rollback 完整實戰與異常回滾模式

     編輯:Java 相關知識

為什麼需要手動事務?

JDBC 預設 自動提交模式:每條 SQL 獨立提交。關閉自動提交的三大理由:

  1. 效能:批量操作減少網絡往返與磁盤同步。
  2. 業務完整性:多表關聯寫入(如訂單+庫存)必須原子成功或失敗。
  3. 分布式事務基礎:兩階段提交(XA)的前置條件。

核心 API 三部曲

Connection conn = dataSource.getConnection();
conn.setAutoCommit(false); // 1. 關閉自動提交
try {
    // 業務 SQL 操作...
    conn.commit();         // 2. 全部成功 → 提交
} catch (SQLException e) {
    conn.rollback();       // 3. 任一失敗 → 回滾
    throw e;
} finally {
    conn.setAutoCommit(true); // 恢復預設,避免連接池污染
    conn.close();
}

完整異常回滾示例

public class JdbcTransactionDemo {
    static final String URL = "jdbc:mysql://localhost:3306/EMP";
    static final String USER = "root";
    static final String PASS = "password";

    public static void main(String[] args) {
        String sql1 = "INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez')";
        String sql2 = "INSERTED INTO Employees VALUES (107, 22, 'Sita', 'Singh')"; // 故意寫錯

        try (Connection conn = DriverManager.getConnection(URL, USER, PASS)) {
            conn.setAutoCommit(false);
            try (Statement stmt = conn.createStatement()) {
                stmt.executeUpdate(sql1);
                stmt.executeUpdate(sql2); // 拋出 SQLException
                conn.commit();
                System.out.println("提交成功");
            } catch (SQLException e) {
                conn.rollback();
                System.out.println("回滾完成: " + e.getMessage());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

輸出:回滾完成: You have an error in your SQL syntax...,兩條 INSERT 均不生效。

事務隔離級別設置

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
// 可選:READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
  • 預設通常為 READ_COMMITTED(Oracle、PostgreSQL、SQL Server)或 REPEATABLE_READ(MySQL InnoDB)。
  • 高隔離級別會增加鎖爭用,根據業務在「一致性」與「並發度」間權衡。

保存點:部分回滾

Savepoint sp = conn.setSavepoint("BEFORE_BATCH");
try {
    batchInsert(conn);
} catch (SQLException e) {
    conn.rollback(sp); // 僅回滾到保存點
    conn.releaseSavepoint(sp);
}

連接池環境下的注意事項

問題後果解決
忘記恢復 autoCommit連接歸還池時仍處於手動模式,後續借用者異常finally 中 conn.setAutoCommit(true)
未關閉資源連接洩漏、游標殘留try-with-resources 或 finally 關閉 Statement/ResultSet
長事務持有連接連接池耗盡、並發下降縮小事務邊界、異步化非關鍵操作

Spring 對比:為何生產建議用聲明式事務?

  • 編程式:事務邏輯散落業務代碼,難以統一維護、易遺漏 rollback()。
  • 聲明式:@Transactional 切面自動織入,異常自動回滾,配置集中管理傳播/隔離/超時/只讀屬性。
💡 最佳實踐:DAO 層僅提供單表 CRUD,Service 層組合多 DAO 操作並加 @Transactional,實現事務邊界與業務邊界對齊。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved