Transaction rollback fail no longer hides original exception

This commit is contained in:
Rsl1122 2019-02-17 22:52:30 +02:00
parent 8870e034e1
commit 1378d3100e
4 changed files with 30 additions and 32 deletions

View File

@ -23,7 +23,7 @@ import java.sql.SQLException;
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public class DBOpException extends RuntimeException { public class DBOpException extends IllegalStateException {
public DBOpException(String message) { public DBOpException(String message) {
super(message); super(message);

View File

@ -108,9 +108,7 @@ public class MySQLDB extends SQLDB {
hikariConfig.setLeakDetectionThreshold(TimeUnit.MINUTES.toMillis(10L)); hikariConfig.setLeakDetectionThreshold(TimeUnit.MINUTES.toMillis(10L));
this.dataSource = new HikariDataSource(hikariConfig); this.dataSource = new HikariDataSource(hikariConfig);
} catch (HikariPool.PoolInitializationException e) {
getConnection();
} catch (HikariPool.PoolInitializationException | SQLException e) {
throw new DBInitException("Failed to set-up HikariCP Datasource: " + e.getMessage(), e); throw new DBInitException("Failed to set-up HikariCP Datasource: " + e.getMessage(), e);
} }
} }
@ -126,11 +124,12 @@ public class MySQLDB extends SQLDB {
try { try {
setupDataSource(); setupDataSource();
// get new connection after restarting pool // get new connection after restarting pool
return dataSource.getConnection(); connection = dataSource.getConnection();
} catch (DBInitException e) { } catch (DBInitException e) {
throw new DBOpException("Failed to restart DataSource after a connection was invalid: " + e.getMessage(), e); throw new DBOpException("Failed to restart DataSource after a connection was invalid: " + e.getMessage(), e);
} }
} }
if (connection.getAutoCommit()) connection.setAutoCommit(false);
return connection; return connection;
} }

View File

@ -64,12 +64,25 @@ public abstract class Transaction {
try { try {
initializeTransaction(db); initializeTransaction(db);
performOperations(); performOperations();
if (connection != null) connection.commit();
success = true; success = true;
} catch (Exception statementFail) {
manageFailure(statementFail); // Throws a DBOpException.
} finally { } finally {
finalizeTransaction(); db.returnToPool(connection);
} }
} }
private void manageFailure(Exception statementFail) {
String failMsg = getClass().getSimpleName() + " failed: " + statementFail.getMessage();
try {
connection.rollback(savepoint);
} catch (SQLException rollbackFail) {
throw new DBOpException(failMsg + ", additionally Transaction rollback failed: " + rollbackFail.getMessage(), statementFail);
}
throw new DBOpException(failMsg + ", Transaction was rolled back.", statementFail);
}
/** /**
* Override this method for conditional execution. * Override this method for conditional execution.
* <p> * <p>
@ -90,37 +103,12 @@ public abstract class Transaction {
private void initializeTransaction(SQLDB db) { private void initializeTransaction(SQLDB db) {
try { try {
this.connection = db.getConnection(); this.connection = db.getConnection();
// Temporary fix for MySQL Patch task test failing, TODO remove after Auto commit is off for MySQL
if (connection.getAutoCommit()) connection.setAutoCommit(false);
this.savepoint = connection.setSavepoint(); this.savepoint = connection.setSavepoint();
} catch (SQLException e) { } catch (SQLException e) {
throw new DBOpException(getClass().getSimpleName() + " initialization failed: " + e.getMessage(), e); throw new DBOpException(getClass().getSimpleName() + " initialization failed: " + e.getMessage(), e);
} }
} }
private void finalizeTransaction() {
try {
handleSavepoint();
// Temporary fix for MySQL Patch task test failing, TODO remove after Auto commit is off for MySQL
if (db.getType() == DBType.MYSQL) connection.setAutoCommit(true);
} catch (SQLException e) {
throw new DBOpException(getClass().getSimpleName() + " finalization failed: " + e.getMessage(), e);
}
if (db != null) db.returnToPool(connection);
}
private void handleSavepoint() throws SQLException {
if (connection == null) {
return;
}
// Commit or rollback the transaction
if (success) {
connection.commit();
} else {
connection.rollback(savepoint);
}
}
protected <T> T query(Query<T> query) { protected <T> T query(Query<T> query) {
return query.executeQuery(db); return query.executeQuery(db);
} }

View File

@ -94,7 +94,7 @@ public class DBPatchMySQLRegressionTest extends DBPatchRegressionTest {
underTest.setTransactionExecutorServiceProvider(MoreExecutors::newDirectExecutorService); underTest.setTransactionExecutorServiceProvider(MoreExecutors::newDirectExecutorService);
underTest.init(); underTest.init();
dropAllTables(underTest); dropAllTables();
// Initialize database with the old table schema // Initialize database with the old table schema
underTest.executeTransaction(new Transaction() { underTest.executeTransaction(new Transaction() {
@ -122,6 +122,17 @@ public class DBPatchMySQLRegressionTest extends DBPatchRegressionTest {
insertData(underTest); insertData(underTest);
} }
private void dropAllTables() {
underTest.executeTransaction(new Transaction() {
@Override
protected void performOperations() {
execute("DROP DATABASE Plan");
execute("CREATE DATABASE Plan");
execute("USE Plan");
}
});
}
@After @After
public void closeDatabase() { public void closeDatabase() {
underTest.close(); underTest.close();