Transactions

Wrap work in inTransaction(). Pika commits when the block finishes and rolls back if it throws. You do not touch the connection, commit, or rollback yourself.

Run in a transaction

Pass a block that returns nothing, or one that returns a value:

orm.inTransaction(() -> {
    new User("Alice").save();
    new User("Bob").save();
});   // commits here; if either save threw, neither row is written

User admin = orm.inTransaction(() -> {
    User u = new User("Charlie");
    u.save();
    new Role("ADMIN").save();
    return u;
});

If the block throws, Pika rolls back everything in it and rethrows the exception.

Nesting

Call inTransaction() inside another and the inner block joins the outer one. Pika counts the nesting and issues a single commit when the outermost block finishes. One failure anywhere rolls back the whole thing.

orm.inTransaction(() -> {            // opens the transaction
    foo.save();

    orm.inTransaction(() -> {        // joins it, no separate commit
        bar.save();
    });

});                                  // foo and bar commit together

Escaping the current transaction

forceTransaction() runs on its own connection and ignores any transaction on the thread. It commits on its own, so its work survives even when the surrounding transaction rolls back. Reach for it when something must persist no matter what, like an audit log.

orm.inTransaction(() -> {
    foo.save();

    orm.forceTransaction(() -> {
        new AuditLog("created foo").save();   // commits immediately, on its own connection
    });

    throw new RuntimeException();   // rolls back foo; the audit log stays
});

Requiring a transaction

joinTransaction() runs its block only if a transaction is already open, and throws IllegalStateException if one is not. Use it in helper methods that must never run on their own.

public void ship(Order order) {
    orm.joinTransaction(() -> {
        order.setStatus("SHIPPED");
        order.save();
    });
}

Checking status

boolean active = orm.isInTransaction();