Connection conn = null;
Savepoint sp = null;
try {
conn = DriverManager.getConnection(url, user, pwd);
conn.setAutoCommit(false); // 開啟事務
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // 設定隔離級別
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO test VALUES(1,'aaa')");
sp = conn.setSavepoint("insert_end"); // 設定保存點
stmt.executeUpdate("UPDATE test SET name='bbb' WHERE id=1");
conn.commit(); // 提交
} catch (SQLException e) {
try {
if (sp != null) conn.rollback(sp); // 回滾到保存點
// conn.rollback(); // 或全量回滾
} catch (SQLException e1) {
throw new RuntimeException("回滾失敗", e);
}
throw new RuntimeException("事務執行失敗", e);
} finally {
if (conn != null) {
try { conn.close(); } catch (SQLException e) { throw new RuntimeException("關閉連接失敗", e); }
}
}
setAutoCommit(false) 等同開啟事務邊界。READ_UNCOMMITTED 到 SERIALIZABLE) 依資料庫與驅動支援度而定,設定不支援的級別通常不報錯但不生效。Savepoint 允許部分回滾,需資料庫與驅動支援 (JDBC 3.0+)。finally 確保連接歸還池,避免洩漏。現代專案幾乎全面使用 Spring @Transactional 或 JTA 容器管理事務,手動 JDBC 事務僅用於輕量級工具、批次腳本或教學示範。