1

Is it possible to invoke DSLContext.transactionResult() multiple times against the same transaction?

I'd like to insert rows into different tables within the same transaction and return the primary keys to the enclosing (non-transactional) code block.

I know that I can probably create some custom return type to hold multiple values but from a code readability perspective it would be preferable to invoke DSLContext.transactionResult() multiple times and pass by an individual result each time.

Gili
  • 86,244
  • 97
  • 390
  • 689

2 Answers2

1

The callable invoked by DSLContext.transactionResult() represents the transaction and is committed or rolled back using the TransactionProvider obtained from Configuration#transactionProvider() once the transaction finishes.

But transactions can be nested (see examples in documentation). So if you have an outer transaction (again using DSLContext.transactionResult()), then you could have a nested transaction for each table you want to insert into within that and probably achieve your goal that way.

knutwannheden
  • 680
  • 4
  • 7
  • I want to pass the inserted row IDs (one per table type) outside the top-most `DSLContext.transactionResult()` block. Nesting transactions would allow me to run the inserts within the same transaction but I cannot pass the values outside of the transaction without playing some tricks (https://stackoverflow.com/a/30026897/14731). Is there a better way? – Gili Aug 03 '19 at 04:08
  • 1
    I am not sure what kind of Java return type you had in mind here. A simple example would be to use a `Map`, where the table name is the key. That would work very well since there would be no need to reassign the variable. Your nested transactions would simply call `Map#put(Object, Object)` and the outer transaction would then return the final result. – knutwannheden Aug 05 '19 at 13:27
0

I concur with Knut's answer. A simple example for this would be:

// The global transaction
List<Integer> result = outer.transactionResult(inner -> {

    // The transactional logic you wish to repeat:
    TransactionalCallable<List<Integer>> block = ctx -> { ... };

    // Your repeated calls to nested transactions, producing separate generated keys, each
    List<Integer> list = new ArrayList<>();
    list.addAll(inner.transactionResult(block));
    list.addAll(inner.transactionResult(block));
    return list;
});
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509