Available in versions: Dev (3.21) | Latest (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11
ExecuteListeners
Supported by ✅ Open Source Edition ✅ Express Edition ✅ Professional Edition ✅ Enterprise Edition
The Configuration lets you specify a list of org.jooq.ExecuteListener instances. 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.
Example: Query statistics ExecuteListener
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;
public class StatisticsListener implements ExecuteListener {
/**
* Generated UID
*/
private static final long serialVersionUID = 7399239846062763212L;
public static final Map<ExecuteType, Integer> STATISTICS = new ConcurrentHashMap<>();
@Override
public void start(ExecuteContext ctx) {
STATISTICS.compute(ctx.type(), (k, v) -> v == null ? 1 : v + 1);
}
}
Now, configure jOOQ's runtime to load your listener
// Create a configuration with an appropriate listener provider: Configuration configuration = new DefaultConfiguration().set(connection).set(dialect); configuration.set(new DefaultExecuteListenerProvider(new StatisticsListener())); // Create a DSLContext from the above configuration DSLContext create = DSL.using(configuration);
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
Example: Custom Logging ExecuteListener
The following depicts an example of a custom ExecuteListener, which pretty-prints all queries being executed by jOOQ to stdout:
import org.jooq.DSLContext;
import org.jooq.ExecuteContext;
import org.jooq.ExecuteListener;
import org.jooq.conf.Settings;
import org.jooq.tools.StringUtils;
public class PrettyPrinter implements ExecuteListener {
/**
* Hook into the query execution lifecycle before executing queries
*/
@Override
public void executeStart(ExecuteContext ctx) {
// Create a new DSLContext for logging rendering purposes
// This DSLContext doesn't need a connection, only the SQLDialect...
DSLContext create = DSL.using(ctx.dialect(),
// ... and the flag for pretty-printing
new Settings().withRenderFormatted(true));
// If we're executing a query
if (ctx.query() != null) {
System.out.println(create.renderInlined(ctx.query()));
}
// If we're executing a routine
else if (ctx.routine() != null) {
System.out.println(create.renderInlined(ctx.routine()));
}
}
}
See also the manual's sections about logging for more sample implementations of actual ExecuteListeners.
Example: Bad query execution ExecuteListener
You can also use ExecuteListeners to interact with your SQL statements, for instance when you want to check if executed UPDATE or DELETE statements contain a WHERE clause. This can be achieved trivially with the following sample ExecuteListener:
public class DeleteOrUpdateWithoutWhereListener implements ExecuteListener {
@Override
public void renderEnd(ExecuteContext ctx) {
if (ctx.sql().matches("^(?i:(UPDATE|DELETE)(?!.* WHERE ).*)$")) {
throw new DeleteOrUpdateWithoutWhereException();
}
}
}
public class DeleteOrUpdateWithoutWhereException extends RuntimeException {}
You might want to replace the above implementation with a more efficient and more reliable one, of course.
Feedback
Do you have any feedback about this page? We'd love to hear it!