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
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
通过 Configuration,您可以指定一个 org.jooq.ExecuteListener
实例列表。ExecuteListener 本质上是 Query、Routine 或 ResultSet 渲染、准备、绑定、执行、获取步骤的事件侦听器。它是日志记录器、调试器、分析器、数据收集器、触发器等的基础类型。高级 ExecuteListener 还可以在适当的方法中为 jOOQ 提供 Connection、PreparedStatement 和 ResultSet 的自定义实现。
示例:查询统计 ExecuteListener
这是一个 ExecuteListener 的示例实现,它只是统计使用 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); } }
现在,配置 jOOQ 的运行时以加载您的侦听器。
// 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);
并随时使用类似这样的代码段记录结果
log.info("STATISTICS"); log.info("----------"); for (ExecuteType type : ExecuteType.values()) { log.info(type.name(), StatisticsListener.STATISTICS.get(type) + " executions"); }
这可能会导致以下日志输出
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
请阅读 ExecuteListener Javadoc
以获取更多详细信息
示例:自定义日志记录 ExecuteListener
以下描述了一个自定义 ExecuteListener 的示例,它将 jOOQ 执行的所有查询以漂亮的格式打印到 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())); } } }
另请参阅手册中关于 日志记录的部分,以获取实际 ExecuteListener 的更多示例实现。
示例:错误的查询执行 ExecuteListener
您还可以使用 ExecuteListeners 与您的 SQL 语句进行交互,例如,当您想检查执行的 UPDATE
或 DELETE
语句是否包含 WHERE
子句时。这可以使用以下示例 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 {}
当然,您可能希望用更有效和更可靠的实现来替换上述实现。
反馈
您对此页面有任何反馈吗? 我们很乐意听到您的声音!