Empleo de puntos de retorno
Los puntos de retorno ofrecen un mecanismo para revertir partes de una transacción. En SQL Server, puede crear un punto de retorno con la instrucción SAVE TRANSACTION nombre_del_punto_de_retorno. Más adelante, ejecute una instrucción ROLLBACK TRANSACTION savepoint_name para revertir al punto de retorno en vez de revertir al inicio de la transacción.
Los puntos de retorno son útiles en situaciones en que no es probable que se produzcan errores. El uso de un punto de retorno para revertir parte de una transacción, en caso de producirse un error no frecuente, puede resultar más eficaz que hacer que cada transacción pruebe si una actualización es válida antes de realizarla. Las operaciones de actualización y reversión son costosas, por lo que los puntos de retorno solamente son eficaces si la probabilidad de encontrar un error es baja y el costo de comprobar de antemano la validez de una actualización es relativamente alto.
El controlador JDBC de Microsoft para SQL Server admite el uso de puntos de retorno mediante el método setSavepoint de la clase SQLServerConnection. Con el método setSavepoint, puede crear un punto de retorno con o sin nombre en la transacción actual y el método devolverá un objeto SQLServerSavepoint. Se pueden crear varios puntos de retorno en una transacción. Para revertir una transacción a un punto de retorno determinado, puede pasar el objeto SQLServerSavepoint al método rollback (java.sql.Savepoint).
En el siguiente ejemplo, se usa un punto de retorno a la vez que se realiza una transacción local consistente en dos instrucciones independientes del bloque try
. Las instrucciones se ejecutan en la tabla Production.ScrapReason de la base de datos de ejemplo de AdventureWorks2022 y se usa un punto de retorno para revertir la segunda instrucción. Como resultado, solo se confirma en la base de datos la primera instrucción.
public static void executeTransaction(Connection con) {
try(Statement stmt = con.createStatement();) {
con.setAutoCommit(false);
stmt.executeUpdate("INSERT INTO Production.ScrapReason(Name) VALUES('Correct width')");
Savepoint save = con.setSavepoint();
stmt.executeUpdate("INSERT INTO Production.ScrapReason(Name) VALUES('Wrong width')");
con.rollback(save);
con.commit();
System.out.println("Transaction succeeded.");
}
catch (SQLException ex) {
ex.printStackTrace();
try {
System.out.println("Transaction failed.");
con.rollback();
}
catch (SQLException se) {
se.printStackTrace();
}
}
}