Hi Marcus,

Thanks for your message.

jOOQ's DefaultTransactionProvider (which you're using as you didn't
override it) supports nested transactions using Savepoints. In other words,
if an outer transaction calls a method that starts an inner transaction,
any exception thrown from the inner transaction will (after rolling back to
the savepoint of the inner transaction) propagate to the outer transaction
and roll back that one as well.

You can avoid using savepoints by telling the DefaultTransactionProvider
not to nest transactions. That way, the exception would just propagate to
the outer-most transaction and roll it back in its entirety.

The way you configured your Configuration might not allow you to work this
way, though. Your nested transaction has to be created using the
configuration that was obtained from the outer transaction. E.g. like this:

public Client save(final Client client) {

    // outer transaction:

    getContext().transaction(configuration -> {

        // do stuff

        // inner transaction:

        DSL.using(configuration).transaction(nested -> {

            // do stuff

}
    });
    return client;
}


An alternative to this model would be to use the
ThreadLocalTransactionProvider, which allows you to use the ThreadLocal
transaction API

public Client save(final Client client) {

    // outer transaction:

    getContext().transaction(() -> {

        // do stuff

        // inner transaction:

        getContext().transaction(() -> {

            // do stuff

}
    });
    return client;
}


Instead of relying on an explicit transaction context (and Configuration
wrapping that context), this API will put the transaction context in a
ThreadLocal variable, as soon as an outer most transaction is started. That
works more like Java EE / Spring / Hibernate.

I hope this helps. Let me know if you have any other questions about this.
Lukas

2017-06-08 11:40 GMT+02:00 Marcus Gattinger <[email protected]>:

> Hi user group,
>
> I'm evaluating jOOQ now for a while and struggle about transaction
> handling.
>
> Currently we use Hibernate in our software and the transaction handling
> works like this:
> We have a Service that is used to begin and commit/rollback a new
> transaction, but only if no transaction has been started.
>
> public void applyInTransaction(final Consumer<HibernateService> action, final 
> SharedSessionContract session) {
>     Transaction tx = null;
>     try {
>         // Start a new transaction if action is executed outside of a 
> transaction.
>         if (session.getTransaction() == null || 
> !session.getTransaction().getStatus().isOneOf(TransactionStatus.ACTIVE)) {
>             tx = session.beginTransaction();
>         }
>
>         action.accept(this);
>
>         // Commit the transaction if it has been started locally.
>         if (tx != null) {
>             tx.commit();
>         }
>     } catch (Exception ex) {
>         // Rollback the transaction if it has been started locally.
>         if (tx != null) {
>             tx.rollback();
>         }
>         throw ex;
>     }
> }
>
>
> As you can see, we use the Hibernate-Session here (i. e. an instance of
> the SharedSessionContract) to decide whether to begin a new transaction or
> not (i. e. there is already a running transaction).
> As a result, the transaction is only committed / rolled back if the
> outmost action has finished. This allows us to use transaction handling on
> any place within our application. Any further inner actions invoked after
> the outer action has been started will "expand" the transaction context. To
> summarize it: At any time only one transaction is started that might cover
> any number of actions.
>
> So how can I migrate this behaviour to jOOQ (ideally using only jOOQ
> itself, no Spring etc.)?
>
> My prototype that I'm using to evaluate jOOQ, I have several repositories,
> each one have a save() method. If a save() method of one repository calls a
> save() method on another repository, I want to commit / rollback all those
> changes after the first (outmost) save() method has finished. You can I
> achieve this? I already have searched the threads in this user group and
> read the jOOQ documentation but have not found anything that points me in
> the right direction.
>
> By the way - a typical repository save() method looks like this:
>
> public Client save(final Client client) {
>     getContext().transaction(configuration -> {
>         ClientRecord record = client.getRecord();
>         record.attach(configuration);
>         if (record.getId() == null) {
>             record.insert();
>         } else {
>             record.update();
>         }
>         // further save() methods of other repository might be called
>     });
>     return client;
> }
>
>
> And the call to getContext() which is a method of the repository base
> class looks like this:
>
> private static final Configuration DEFAULT_CONFIGURATION = new 
> DefaultConfiguration()
>         .set(DataSource.get())
>         .set(SQLDialect.MYSQL)
>         .set(new Settings().withRenderSchema(false).withRenderCatalog(false));
>
> protected DSLContext getContext() {
>     return DSL.using(DEFAULT_CONFIGURATION);
> }
>
>
> If any further information is required to clarify my request, do not
> hesitate to ask for that.
>
> Kind regards,
> Marcus
>
> --
> You received this message because you are subscribed to the Google Groups
> "jOOQ User Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups "jOOQ 
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to