Search code examples
javasqljooq

Correlate jOOQ transaction & record listeners


Is there a way to correlate jOOQ transaction & record listeners?

I need to trigger certain actions once records where added to a certain table. RecordListener#insertEnd is the proper hook for that but to my knowledge this does not guarantee that the records were really inserted. The transaction may still rollback after insertEnd() was called - or the insert to one table may be part of a batch of inserts that also affects other tables.

If, on the other hand, I implement TransactionListener#comitEnd I can't figure out which records where actually inserted. TransactionContext doesn't have this information.


Solution

  • You can do this by accessing the Configuration.data() property, which has been created for this purpose. Consider these two listeners:

    class RL extends DefaultRecordListener {
        @Override
        public void insertEnd(RecordContext ctx) {
            // Put some property into the data map
            ctx.configuration().data("x", "y");
        }
    }
    
    class TL extends DefaultTransactionListener {
        String x;
    
        @Override
        public void commitEnd(TransactionContext ctx) {
            // Retrieve the property again
            x = (String) ctx.configuration().data("x");
        }
    }
    

    This could then be used as follows:

    RL rl = new RL();
    TL tl = new TL();
    
    ctx.configuration()
       .derive(rl)
       .derive(tl)
       .dsl()
       .transaction(c -> {
            assertNull(c.data("x"));
    
            TRecord t = c.dsl().newRecord(T);
            t.setA("a");
            t.setB("b");
    
            // insertEnd() triggered here
            assertEquals(1, t.insert());
            assertEquals("y", c.data("x"));
    
        // commitEnd() triggered here
        });
    
    // Since the transaction creates a nested, derived scope, you don't see these things
    // from the outside of the transaction in your possibly global Configuration
    assertNull(ctx.data("x"));
    assertNull(ctx.configuration().data("x"));
    assertEquals("y", tl.x);