首页 > 解决方案 > 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.

标签: javasqljooq

解决方案


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);

推荐阅读