Share jOOQ on Facebook
Share jOOQ on Twitter

This page in other versions: 3.10 | 3.9 | 3.8 | 3.7 | 3.6 | 3.5 | 3.4 | 3.3 | Old, end-of-life releases: 3.2 | 3.1 | 3.0 | 2.6 | 2.5

The jOOQ Factory Settings let you specify a list of org.jooq.ExecuteListener classes. The ExecuteListener is essentially an event listener for Query, Routine, or ResultSet render, prepare, bind, execute, fetch steps. It is a base type for loggers, debuggers, profilers, data collectors, triggers, etc. Advanced ExecuteListeners can also provide custom implementations of Connection, PreparedStatement and ResultSet to jOOQ in apropriate methods.

For convenience and better backwards-compatibility, consider extending org.jooq.impl.DefaultExecuteListener instead of implementing this interface.

Here is a sample implementation of an ExecuteListener, that is simply counting the number of queries per type that are being executed using jOOQ:

package com.example;

// Extending DefaultExecuteListener, which provides empty implementations for all methods...
public class StatisticsListener extends DefaultExecuteListener {
    public static Map<ExecuteType, Integer> STATISTICS = new HashMap<ExecuteType, Integer>();

    // Count "start" events for every type of query executed by jOOQ
    @Override
    public void start(ExecuteContext ctx) {
        synchronized (STATISTICS) {
            Integer count = STATISTICS.get(ctx.type());
    
            if (count == null) {
                count = 0;
            }
    
            STATISTICS.put(ctx.type(), count + 1);
        }
    }
}

Now, configure jOOQ's runtime to load your listener

<settings>
  <executeListeners>
    <executeListener>com.example.StatisticsListener</executeListener>
  </executeListeners>
</settings>

And log results any time with a snippet like this:

log.info("STATISTICS");
log.info("----------");

for (ExecuteType type : ExecuteType.values()) {
    log.info(type.name(), StatisticsListener.STATISTICS.get(type) + " executions");
}

This may result in the following log output:

15:16:52,982  INFO - TEST STATISTICS
15:16:52,982  INFO - ---------------
15:16:52,983  INFO - READ                     : 919 executions
15:16:52,983  INFO - WRITE                    : 117 executions
15:16:52,983  INFO - DDL                      : 2 executions
15:16:52,983  INFO - BATCH                    : 4 executions
15:16:52,983  INFO - ROUTINE                  : 21 executions
15:16:52,983  INFO - OTHER                    : 30 executions

Please read the ExecuteListener Javadoc for more details

Writing a custom ExecuteListener for logging

The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout:

import org.jooq.ExecuteContext;
import org.jooq.conf.Settings;
import org.jooq.impl.DefaultExecuteListener;
import org.jooq.impl.Factory;
import org.jooq.tools.StringUtils;

public class PrettyPrinter extends DefaultExecuteListener {

    /**
     * Hook into the query execution lifecycle before executing queries
     */
    @Override
    public void executeStart(ExecuteContext ctx) {

        // Create a new factory for logging rendering purposes
        // This factory doesn't need a connection, only the SQLDialect...
        Factory factory = new Factory(ctx.getDialect(),
        
        // ... and the flag for pretty-printing
        	new Settings().withRenderFormatted(true));

        // If we're executing a query
        if (ctx.query() != null) {
            System.out.println(factory.renderInlined(ctx.query()));
        }
        
        // If we're executing a routine
        else if (ctx.routine() != null) {
            System.out.println(factory.renderInlined(ctx.routine()));
        }
        
        // If we're executing anything else (e.g. plain SQL)
        else if (!StringUtils.isBlank(ctx.sql())) {
            System.out.println(ctx.sql());
        }
    }
}

See also the manual's sections about logging and the jOOQ Console for more sample implementations of actual ExecuteListeners.

The jOOQ Logo