ENH: Add Transaction.rollbackAndContinue()

Typically useful for handling DuplicateKeyException where we expect
DuplicateKeyException to be thrown and catch it with the intention of
continuing processing using the same transaction.

Note that some databases like Oracle do not require this explicit
rollback() and would work without the rollbackAndContinue(). Postgres
in particular requires the rollback() call on the underlying connection
such that we can continue using that transaction/java.sql.Connection.

Note that in the existing test we can see that rollbackAndContinue()
is pretty close to being syntactic sugar. I think adding rollbackAndContinue()
is justified and complements the existing commitAndContinue().
This commit is contained in:
Rob Bygrave
2022-09-01 17:08:11 +12:00
parent 563340edbd
commit 7df168f232
6 changed files with 96 additions and 28 deletions
@@ -1,16 +1,15 @@
package org.tests.insert;
import io.ebean.xtest.BaseTestCase;
import io.ebean.DB;
import io.ebean.DuplicateKeyException;
import io.ebean.annotation.Transactional;
import io.ebean.xtest.BaseTestCase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tests.model.draftable.Document;
import java.sql.SQLException;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -92,14 +91,8 @@ public class TestInsertDuplicateKey extends BaseTestCase {
DB.getDefault().currentTransaction().flush();
} catch (DuplicateKeyException e) {
log.info("duplicate failed but just continue" + e.getMessage());
try {
// typically we would use transaction.commitAndContinue()
// ... this is a rollback and continue type scenario
// ... more sensible to use a second transaction that do this
DB.getDefault().currentTransaction().connection().rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
// rollback and continue using the transaction
DB.getDefault().currentTransaction().rollbackAndContinue();
}
Document doc0 = new Document();