transacción - rollback java
En JDBC, cuando la confirmación automática es falsa y no se han establecido puntos de rescate explícitos, ¿es un buen estilo o un desperdicio para deshacer? (2)
El cierre debe retrotraerse porque no se comprometerá cuando se liberen los recursos, pero es bueno que el manejo de errores sea específico, por lo que si desea revertir una excepción, hágalo. Entonces puedes hacer tu limpieza en un bloque {} final. La reversión () se produce solo en caso de error, en cuyo caso su confirmación () no se realizó correctamente o ni siquiera se alcanzó.
Connection conn = null;
try {
conn = ...
...
conn.commit();
}
catch (SQLException e) {
if (conn != null) {
conn.rollback();
}
}
finally {
if (conn != null) {
conn.close();
}
}
Supongamos que tiene el siguiente código:
Connection conn;
try
{
conn = ... // get connection
conn.setAutoCommit(false);
... // Do some modification queries and logic
conn.commit()
} catch(SQLException e)
{
conn.rollback() // Do we need this?
conn.close()
}
En este código, si hay una excepción, ¿es mejor estilo simplemente cerrar la conexión (ya que el autocommit está desactivado), o retroceder explícitamente y luego cerrar la conexión? No hay puntos guardados.
Siento que podría tener sentido agregar la llamada de restitución porque:
1) Alguien, en el futuro, podría agregar puntos de guardado, pero se olvida de agregar la reversión
2) Mejora la legibilidad
3) No debería costar nada, ¿verdad?
Pero, obviamente, ninguno de estos es particularmente convincente. ¿Alguna práctica estándar?
Nota: Soy consciente de la necesidad de repetir el try / catch al cerrar y retroceder. De hecho, tengo un middleware que abstrae el acceso a la base de datos y se ocupa de eso, pero me preguntaba si agregarlo era superfluo.
La expresión normal es la siguiente:
public void executeSomeQuery() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SOME_SQL)) {
// Fire transactional queries here.
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
Tenga en cuenta que la sentencia try-with-resources de Java 7 siempre llama implícitamente a close()
en el recurso cuando finaliza el bloque try
, como si finally
ocurriera.
La llamada al rollback()
también es obligatoria cuando se trata de una conexión agrupada . A saber, restablecerá el estado transaccional de la conexión. El close()
de una conexión agrupada no hará eso, solo el commit()
y rollback()
lo harán. No llamar a rollback()
puede llevar a que la próxima concesión de la conexión agrupada aún tenga las consultas (correctas) de la transacción anterior en su memoria.
Ver también javadoc de Connection#close()
(énfasis no mío):
Se recomienda encarecidamente que una aplicación confirme o retrotraiga explícitamente una transacción activa antes de llamar al método de
close
. Si se llama al métodoclose
y hay una transacción activa, los resultados están definidos por la implementación.