I'm using JavaEE/JPA managed transactions with Oracle DB und Hibernate and need to achieve some kind of nested transaction. As far as I've learned such thing is not supported out of the box but I should be able to use savepoints for that purpose.
As suggested by https://stackoverflow.com/a/7626387/173689 I've tried the following:
@Transactional(value = TxType.REQUIRES_NEW)
public boolean doImport(Import importer, Row row) throws ImportRowFailedException {
// stripped code ...
// We need to try different possibilities from which one may succeed...
// ...former failures must be rolled back!
for (Possibility poss : importer.getPossibilities()) {
if (this.tryPossibility(poss, row)) break;
}
// stripped code ...
}
public boolean tryPossibility(Possibility possibility, Row row) {
try {
Session session = this.em.unwrap(Session.class);
session.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
Savepoint before = connection.setSavepoint();
if (!possibility.importRow(row)) {
connection.rollback(before);
throw new ImportRowFailedException();
}
}
});
}
catch (ImportRowFailedException ex) {
return false;
}
return true;
}
Upon connection.rollback(before)
I get the following exception:
Caused by: java.sql.SQLException: IJ031040: Connection is not associated with a managed connection: org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@40a6a460
at org.jboss.jca.adapters.jdbc.WrappedConnection.lock(WrappedConnection.java:164)
at org.jboss.jca.adapters.jdbc.WrappedConnection.rollback(WrappedConnection.java:883)
How must I deal with that?
The initial
java.sql.SQLException: IJ031040
seems related to a specific outcome during our import. It later has been replaced with anotherjava.sql.SQLException
that forbid the rollback for managed transactions. But I could finally solve the problem by issuing native SQL statements:This allows a "nested Transaction" within the larger one and solved my problems.