Search in sources :

Example 1 with SerializableTransactionRunner

use of org.jdbi.v3.core.transaction.SerializableTransactionRunner in project jdbi by jdbi.

the class TransactionTest method serializableTransaction.

@Test
public void serializableTransaction() throws Exception {
    // tag::serializable[]
    // Automatically rerun transactions
    db.setTransactionHandler(new SerializableTransactionRunner());
    // Set up some values
    BiConsumer<Handle, Integer> insert = (h, i) -> h.execute("INSERT INTO ints(value) VALUES(?)", i);
    handle.execute("CREATE TABLE ints (value INTEGER)");
    insert.accept(handle, 10);
    insert.accept(handle, 20);
    // Run the following twice in parallel, and synchronize
    ExecutorService executor = Executors.newCachedThreadPool();
    CountDownLatch latch = new CountDownLatch(2);
    Callable<Integer> sumAndInsert = () -> db.inTransaction(TransactionIsolationLevel.SERIALIZABLE, h -> {
        // Both read initial state of table
        int sum = h.select("SELECT sum(value) FROM ints").mapTo(int.class).findOnly();
        // First time through, make sure neither transaction writes until both have read
        latch.countDown();
        latch.await();
        // Now do the write.
        insert.accept(h, sum);
        return sum;
    });
    // Both of these would calculate 10 + 20 = 30, but that violates serialization!
    Future<Integer> result1 = executor.submit(sumAndInsert);
    Future<Integer> result2 = executor.submit(sumAndInsert);
    // One of the transactions gets 30, the other will abort and automatically rerun.
    // On the second attempt it will compute 10 + 20 + 30 = 60, seeing the update from its sibling.
    // This assertion fails under any isolation level below SERIALIZABLE!
    assertThat(result1.get() + result2.get()).isEqualTo(30 + 60);
    executor.shutdown();
// end::serializable[]
}
Also used : Arrays(java.util.Arrays) Transaction(org.jdbi.v3.sqlobject.transaction.Transaction) SqlUpdate(org.jdbi.v3.sqlobject.statement.SqlUpdate) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) SqlObject(org.jdbi.v3.sqlobject.SqlObject) Callable(java.util.concurrent.Callable) TransactionException(org.jdbi.v3.core.transaction.TransactionException) Future(java.util.concurrent.Future) Handle(org.jdbi.v3.core.Handle) BiConsumer(java.util.function.BiConsumer) ClassRule(org.junit.ClassRule) JdbiRule(org.jdbi.v3.testing.JdbiRule) ExpectedException(org.junit.rules.ExpectedException) ExecutorService(java.util.concurrent.ExecutorService) SqlQuery(org.jdbi.v3.sqlobject.statement.SqlQuery) Before(org.junit.Before) Jdbi(org.jdbi.v3.core.Jdbi) TransactionIsolationLevel(org.jdbi.v3.core.transaction.TransactionIsolationLevel) Test(org.junit.Test) SerializableTransactionRunner(org.jdbi.v3.core.transaction.SerializableTransactionRunner) Executors(java.util.concurrent.Executors) CountDownLatch(java.util.concurrent.CountDownLatch) Rule(org.junit.Rule) Optional(java.util.Optional) User(jdbi.doc.ResultsTest.User) ConstructorMapper(org.jdbi.v3.core.mapper.reflect.ConstructorMapper) PostgresDbRule(org.jdbi.v3.postgres.PostgresDbRule) ExecutorService(java.util.concurrent.ExecutorService) SerializableTransactionRunner(org.jdbi.v3.core.transaction.SerializableTransactionRunner) CountDownLatch(java.util.concurrent.CountDownLatch) Handle(org.jdbi.v3.core.Handle) Test(org.junit.Test)

Aggregations

Arrays (java.util.Arrays)1 Optional (java.util.Optional)1 Callable (java.util.concurrent.Callable)1 CountDownLatch (java.util.concurrent.CountDownLatch)1 ExecutorService (java.util.concurrent.ExecutorService)1 Executors (java.util.concurrent.Executors)1 Future (java.util.concurrent.Future)1 BiConsumer (java.util.function.BiConsumer)1 User (jdbi.doc.ResultsTest.User)1 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)1 Handle (org.jdbi.v3.core.Handle)1 Jdbi (org.jdbi.v3.core.Jdbi)1 ConstructorMapper (org.jdbi.v3.core.mapper.reflect.ConstructorMapper)1 SerializableTransactionRunner (org.jdbi.v3.core.transaction.SerializableTransactionRunner)1 TransactionException (org.jdbi.v3.core.transaction.TransactionException)1 TransactionIsolationLevel (org.jdbi.v3.core.transaction.TransactionIsolationLevel)1 PostgresDbRule (org.jdbi.v3.postgres.PostgresDbRule)1 SqlObject (org.jdbi.v3.sqlobject.SqlObject)1 SqlQuery (org.jdbi.v3.sqlobject.statement.SqlQuery)1 SqlUpdate (org.jdbi.v3.sqlobject.statement.SqlUpdate)1