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

Java JDBC 中使用 Savepoint 實現事務回滾保存點完整教學

     編輯:Java 相關知識

前言

JDBC 3.0 引入 Savepoint 介面,允許在事務中設定邏輯回滾點,發生錯誤時可選擇回滾至特定保存點而非整個事務,極大提升了資料庫操作的靈活性。本文詳細講解 Savepoint 核心 API、使用流程與完整代碼範例。

一、核心 API 速查

方法說明
Connection.setSavepoint(String name)建立命名保存點,回傳 Savepoint 物件
Connection.releaseSavepoint(Savepoint sp)釋放指定保存點
Connection.rollback(Savepoint sp)回滾至指定保存點

二、基本使用範例

try (Connection conn = DriverManager.getConnection(url, user, pass)) {
    conn.setAutoCommit(false); // 開啟事務

    Savepoint sp1 = conn.setSavepoint("SP_BEFORE_INSERT");
    stmt.executeUpdate("INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez')");

    // 故意執行錯誤 SQL
    stmt.executeUpdate("INSERTED INTO Employees VALUES (107, 22, 'Sita', 'Tez')"); // 語法錯

    conn.commit(); // 若無錯誤提交
} catch (SQLException e) {
    conn.rollback(sp1); // 回滾至保存點,第一條 INSERT 也會被撤銷
}

三、完整可執行範例 (MySQL)

import java.sql.*;

public class JDBCSavepointDemo {
    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) {
        try (Connection conn = DriverManager.getConnection(URL, USER, PASS)) {
            conn.setAutoCommit(false);
            try (Statement stmt = conn.createStatement()) {
                // 1. 查詢初始資料
                printRs(stmt.executeQuery("SELECT id, first, last, age FROM Employees"));

                // 2. 刪除 ID=110 前設保存點
                Savepoint sp1 = conn.setSavepoint("DEL_110");
                stmt.executeUpdate("DELETE FROM Employees WHERE ID = 110");
                System.out.println("已刪除 ID=110");

                // 3. 發現刪錯,回滾至 sp1
                conn.rollback(sp1);
                System.out.println("已回滾至 DEL_110 保存點");

                // 4. 正確刪除 ID=95 前設另一保存點
                Savepoint sp2 = conn.setSavepoint("DEL_95");
                stmt.executeUpdate("DELETE FROM Employees WHERE ID = 95");

                // 5. 最終結果
                printRs(stmt.executeQuery("SELECT id, first, last, age FROM Employees"));
                conn.commit();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    static void printRs(ResultSet rs) throws SQLException {
        rs.beforeFirst();
        while (rs.next()) {
            System.out.printf("ID: %d, Age: %d, First: %s, Last: %s%n",
                    rs.getInt("id"), rs.getInt("age"), rs.getString("first"), rs.getString("last"));
        }
        System.out.println("---");
    }
}

四、執行結果說明

初始資料:
ID: 95, Age: 20, First: Sima, Last: Chug
ID: 100, Age: 18, First: Zara, Last: Ali
...
ID: 110, Age: 20, First: Sima, Last: Chug

已刪除 ID=110
已回滾至 DEL_110 保存點  <-- ID=110 恢復
最終資料 (ID=95 被刪除):
ID: 100, Age: 18, First: Zara, Last: Ali
...
ID: 110, Age: 20, First: Sima, Last: Chug  <-- ID=110 仍在
ID: 95 已不存在

五、最佳實踐與注意事項

  1. 必須關閉自動提交:conn.setAutoCommit(false),否則每條 SQL 即時提交,保存點無效。
  2. 保存點僅在當前事務有效:提交或回滾整個事務後,保存點自動失效。
  3. 釋放不再需要的保存點:releaseSavepoint() 可釋放資源,避免記憶體洩漏。
  4. 資料庫支援度:Oracle、PostgreSQL、MySQL (InnoDB)、SQL Server 均支援;部分較舊 DBMS 可能不支援。
  5. 巢狀保存點:可建立多層保存點,回滾至較早點會自動釋放該點之後的保存點。

六、總結

Savepoint 讓複雜業務邏輯(如多步驟訂單處理、批次匯入驗證)能精細控制事務邊界,配合 rollback(Savepoint) 可大幅減少重試成本,是 JDBC 進階開發必備技能。

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