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
*/
public class DBOpException extends RuntimeException {
public class DBOpException extends IllegalStateException {
public DBOpException(String message) {
super(message);

View File

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

View File

@ -64,12 +64,25 @@ public abstract class Transaction {
try {
initializeTransaction(db);
performOperations();
if (connection != null) connection.commit();
success = true;
} catch (Exception statementFail) {
manageFailure(statementFail); // Throws a DBOpException.
} 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.
* <p>
@ -90,37 +103,12 @@ public abstract class Transaction {
private void initializeTransaction(SQLDB db) {
try {
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();
} catch (SQLException 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) {
return query.executeQuery(db);
}

View File

@ -94,7 +94,7 @@ public class DBPatchMySQLRegressionTest extends DBPatchRegressionTest {
underTest.setTransactionExecutorServiceProvider(MoreExecutors::newDirectExecutorService);
underTest.init();
dropAllTables(underTest);
dropAllTables();
// Initialize database with the old table schema
underTest.executeTransaction(new Transaction() {
@ -122,6 +122,17 @@ public class DBPatchMySQLRegressionTest extends DBPatchRegressionTest {
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
public void closeDatabase() {
underTest.close();