我们有一个用于记录数据库查询的自定义执行侦听器,我们如何过滤掉仅针对某些表名记录的查询? 目前执行的每个查询都会被记录下来。
这是我们目前的倾听者。
@Override
public void executeStart(ExecuteContext ctx) {
// Create a new DSLContext for logging rendering purposes
// This DSLContext doesn't need a connection, only the SQLDialect...
Settings setting = new Settings();
setting.withRenderFormatted(true);
setting.setExecuteLogging(true);
StringBuilder message = new StringBuilder();
DSLContext create = DSL.using(ctx.configuration().dialect(),
// ... and the flag for pretty-printing
new Settings().withRenderFormatted(true));
// If we're executing a query
if (ctx.query() != null && ENABLE_LOGGING) {
LOGGER.debug(message.append(DynamicApplicationConfig.getStringProperty("API_ENV","dev"))
.append(" - ")
.append(create.renderInlined(ctx.query())).toString());
}
// If we're executing a routine
else if (ctx.routine() != null && ENABLE_LOGGING) {
LOGGER.debug(message.append(DynamicApplicationConfig.getStringProperty("API_ENV","dev"))
.append(" - ")
.append(create.renderInlined(ctx.routine())).toString());
}
// If we're executing anything else (e.g. plain SQL)
else if (!StringUtils.isBlank(ctx.sql()) && ENABLE_LOGGING) {
LOGGER.debug(message.append(DynamicApplicationConfig.getStringProperty("API_ENV","dev"))
.append(" - ")
.append(ctx.sql()).toString());
}
}
答案 0 :(得分:1)
RenderContext
jOOQ查询通过RenderContext
API生成一个SQL字符串,这是一个传递给每个jOOQ QueryPart
的API,以便生成SQL字符串内容和绑定变量。您可以实现自己的并通过查询传递它,以便收集查询中包含的所有表。
请注意,RenderContext
API可能会在以后的次要版本中收到新方法,因此这种实现可能会在版本之间中断。
VisitListener
jOOQ知道VisitListener
SPI,它允许您挂钩渲染生命周期。这个SPI的想法是能够修改生成的SQL内容(e.g. to implement more sophisticated multi-tenancy or row level security features)。
在您的情况下,您不会操纵jOOQ表达式树,而只是收集正在渲染的所有表,并将它们存储在记录器可访问的某个位置。
此解决方案可能对渲染性能产生很小的影响。
为了完整性'为了清楚(因为我确定你自己已经想过这个),我列出了一个简单的解决方案,只有当某个正则表达式与SQL字符串匹配时才会记录消息,例如:
if (ctx.query() != null && ENABLE_LOGGING
&& ctx.sql().matches("(?i:.*?\\bmy_table_name\\b.*)") {
LOGGER.debug(message.append(
DynamicApplicationConfig.getStringProperty("API_ENV","dev"))
.append(" - ")
.append(create.renderInlined(ctx.query())).toString());
}
当然,您的实际正则表达式可能更复杂
当然,您可以尝试访问存储表引用的ctx.query()
内部。我不是在这里记录这个,因为它可能会发生变化,属于内部。
但为了完整性'值得一提的是,因为这可能是一个很好的解决方案。