Java 和 MySQL - SavePoint

新的 JDBC 3.0 Savepoint 接口为您提供了额外的事务控制。大多数现代 DBMS 都支持其环境中的保存点,例如 Oracle 的 PL/SQL。

设置保存点时,您会在事务中定义逻辑回滚点。如果在保存点之后发生错误,您可以使用回滚方法撤消所有更改或仅撤消保存点之后所做的更改。

Connection 对象有两种新方法可帮助您管理保存点 −

  • setSavepoint(String savepointName) − 定义一个新的保存点。它还返回一个 Savepoint 对象。

  • releaseSavepoint(Savepoint savepointName) − 删除保存点。请注意,它需要一个 Savepoint 对象作为参数。此对象通常是 setSavepoint() 方法生成的保存点。

有一个 rollback (String savepointName) 方法,它将工作回滚到指定的保存点。

以下示例说明了 Savepoint 对象的用法 −

try{
    //假设一个有效的连接对象 conn
    conn.setAutoCommit(false);
    语句 stmt = conn.createStatement();
    
    //设置一个保存点
    保存点 savepoint1 = conn.setSavepoint("Savepoint1");
    String SQL = "INSERT INTO Employees " +
    "VALUES (106, 20, 'Rita', 'Tez')";
    stmt.executeUpdate(SQL);
    //提交一个格式错误的 SQL 语句,该语句会中断
    String SQL = "INSERTED IN Employees " +
    "VALUES (107, 22, 'Sita', 'Tez')";
    stmt.executeUpdate(SQL);
    // 如果没有错误,则提交更改。
    conn.commit();

}catch(SQLException se){
   // 如果有任何错误。
   conn.rollback(savepoint1);
}

在这种情况下,上述 INSERT 语句均不会成功,所有内容都将回滚。

以下是使用 setSavepointrollback 的示例。

此示例代码是根据前面章节中完成的环境和数据库设置编写的。

将以下示例复制并粘贴到 TestApplication.java 中,然后按如下方式编译并运行 −

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;

public class TestApplication {
   static final String DB_URL = "jdbc:mysql://localhost/TUTORIALSPOINT";
   static final String USER = "guest";
   static final String PASS = "guest123";
   static final String QUERY = "SELECT id, first, last, age FROM Employees";
   static final String DELETE_QUERY = "DELETE FROM Employees WHERE ID = 8";
   static final String DELETE_QUERY_1 = "DELETE FROM Employees WHERE ID = 9";

   public static void printResultSet(ResultSet rs) throws SQLException{
      // 确保我们从第一行开始
      rs.beforeFirst();
      while(rs.next()){
         // 显示值
         System.out.print("ID: " + rs.getInt("id"));
         System.out.print(", Age: " + rs.getInt("age"));
         System.out.print(", First: " + rs.getString("first"));
         System.out.println(", Last: " + rs.getString("last"));
      }
      System.out.println();
   }

   public static void main(String[] args) {
      // 打开连接
      try(Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
         Statement stmt = conn.createStatement(
            ResultSet.TYPE_SCROLL_INSENSITIVE,
            ResultSet.CONCUR_UPDATABLE);				
      ) {		

        conn.setAutoCommit(false);
        ResultSet rs = stmt.executeQuery(QUERY);
        System.out.println("列出结果集以供参考....");
        printResultSet(rs);
        
        // 删除 ID = 8 的行
        // 但在执行此操作之前保存点。
        Savepoint savepoint1 = conn.setSavepoint("ROWS_DELETED_1");
        System.out.println("正在删除行....");
        stmt.executeUpdate(DELETE_QUERY);
        // 回滚保存点 1 之后的更改。
        conn.rollback(savepoint1);
        
        // 删除 ID = 9 的行
        // 但在执行此操作之前保存点。
        conn.setSavepoint("ROWS_DELETED_2");
        System.out.println("正在删除行....");
        
        stmt.executeUpdate(DELETE_QUERY_1);
        
        rs = stmt.executeQuery(QUERY);
        System.out.println("列出结果集以供参考....");
        printResultSet(rs);
        
        // 清理环境
        rs.close();

      } catch (SQLException e) {
         e.printStackTrace();
      } 
   }
}

现在,让我们编译上面的例子,如下所示 −

C:\>javac TestApplication.java
C:\>

当您运行 TestApplication 时,它会产生以下结果 −

C:\>java TestApplication
List result set for reference....
ID: 1, Age: 23, First: Zara, Last: Ali
ID: 2, Age: 30, First: Mahnaz, Last: Fatma
ID: 3, Age: 35, First: Zaid, Last: Khan
ID: 4, Age: 33, First: Sumit, Last: Mittal
ID: 5, Age: 40, First: John, Last: Paul
ID: 7, Age: 20, First: Sita, Last: Singh
ID: 8, Age: 20, First: Rita, Last: Tez
ID: 9, Age: 20, First: Sita, Last: Singh

Deleting row....
Deleting row....
List result set for reference....
ID: 1, Age: 23, First: Zara, Last: Ali
ID: 2, Age: 30, First: Mahnaz, Last: Fatma
ID: 3, Age: 35, First: Zaid, Last: Khan
ID: 4, Age: 33, First: Sumit, Last: Mittal
ID: 5, Age: 40, First: John, Last: Paul
ID: 7, Age: 20, First: Sita, Last: Singh
ID: 8, Age: 20, First: Rita, Last: Tez
C:\>