JOOQ 侦听器:两个查询之间未清除上下文数据
JOOQ listeners: context data is not cleaned between two queries
在我目前的项目中,我使用java11/JOOQ 3.15/Micronaut/Micrometer。为了获得相关的 SQL 指标,我想在我的 JOOQ 查询中添加一个名称。
为此,我尝试将 ctx.data()
字段与自定义 ExecuteListener 结合使用。
让我们来看一个真正简化的监听器:
@Singleton
public class JooqListener extends DefaultExecuteListener {
transient StopWatch watch;
private final MeterRegistry meterRegistry;
public JooqListener(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@Override
public void executeStart(ExecuteContext ctx) {
watch = new StopWatch();
}
@Override
public void fetchEnd(ExecuteContext ctx) {
Tags prometheusTag = Tags.of("queryName", ctx.configuration().data("queryName").toString());
meterRegistry.timer("sql.query.timer", prometheusTag)
.record(watch.split(), TimeUnit.NANOSECONDS);
}
// I have tried to remove the data manually, but not working
@Override
public void end(ExecuteContext ctx) {
ctx.configuration().data().remove("queryName");
}
}
如果我从两个不同的存储库发送 2 个不同的查询,例如:
DSLContext context = DSL.using(jooqConfiguration);
context.data("queryName", "query1");
return context.select(1).from("dual").fetch();
然后,假设我不专心,忘记命名我的查询:
DSLContext context = DSL.using(jooqConfiguration);
return context.select(2).from("dual").fetch();
ctx.configuration().data("queryName")
在我的侦听器中将始终包含“query1”,这是我没想到的,因为ExecuteListeners 正在逐个查询地侦听,而且我创建了两个不同的DSLContext。看起来 ctx.data()
无法清除,只能被覆盖。
这是预期的行为吗?我应该使用其他可以限制在查询范围内的 object/method 吗? (我在 google 上搜索了很多,但“数据”关键字有点烦人...)
谢谢
一个DSLContext
只是包裹了一个Configuration
。它没有自己的生命周期。因此,如果您通过 DSLContext
修改 Configuration.data()
映射,您就是在修改全局共享对象。换句话说,你不能修改 Configuration.data()
除了你第一次初始化你的配置。 See this section of the manual for more details.
完成您打算做的事情的更好方法是:
// Create a "derived" configuration, which is a new,
// independent Configuration instance
DSLContext context = DSL.using(jooqConfiguration.derive());
context.data("queryName", "query1");
return context.select(1).from("dual").fetch();
然后,在你的 ExecuteListener
:
@Override
public void fetchEnd(ExecuteContext ctx) {
// Reading the Configuration.data() is still fine:
Tags prometheusTag = Tags.of("queryName",
ctx.configuration().data("queryName").toString());
meterRegistry.timer("sql.query.timer", prometheusTag)
.record(watch.split(), TimeUnit.NANOSECONDS);
}
@Override
public void end(ExecuteContext ctx) {
// But you shouldn't modify it
ctx.configuration().data().remove("queryName");
}
在我目前的项目中,我使用java11/JOOQ 3.15/Micronaut/Micrometer。为了获得相关的 SQL 指标,我想在我的 JOOQ 查询中添加一个名称。
为此,我尝试将 ctx.data()
字段与自定义 ExecuteListener 结合使用。
让我们来看一个真正简化的监听器:
@Singleton
public class JooqListener extends DefaultExecuteListener {
transient StopWatch watch;
private final MeterRegistry meterRegistry;
public JooqListener(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@Override
public void executeStart(ExecuteContext ctx) {
watch = new StopWatch();
}
@Override
public void fetchEnd(ExecuteContext ctx) {
Tags prometheusTag = Tags.of("queryName", ctx.configuration().data("queryName").toString());
meterRegistry.timer("sql.query.timer", prometheusTag)
.record(watch.split(), TimeUnit.NANOSECONDS);
}
// I have tried to remove the data manually, but not working
@Override
public void end(ExecuteContext ctx) {
ctx.configuration().data().remove("queryName");
}
}
如果我从两个不同的存储库发送 2 个不同的查询,例如:
DSLContext context = DSL.using(jooqConfiguration);
context.data("queryName", "query1");
return context.select(1).from("dual").fetch();
然后,假设我不专心,忘记命名我的查询:
DSLContext context = DSL.using(jooqConfiguration);
return context.select(2).from("dual").fetch();
ctx.configuration().data("queryName")
在我的侦听器中将始终包含“query1”,这是我没想到的,因为ExecuteListeners 正在逐个查询地侦听,而且我创建了两个不同的DSLContext。看起来 ctx.data()
无法清除,只能被覆盖。
这是预期的行为吗?我应该使用其他可以限制在查询范围内的 object/method 吗? (我在 google 上搜索了很多,但“数据”关键字有点烦人...)
谢谢
一个DSLContext
只是包裹了一个Configuration
。它没有自己的生命周期。因此,如果您通过 DSLContext
修改 Configuration.data()
映射,您就是在修改全局共享对象。换句话说,你不能修改 Configuration.data()
除了你第一次初始化你的配置。 See this section of the manual for more details.
完成您打算做的事情的更好方法是:
// Create a "derived" configuration, which is a new,
// independent Configuration instance
DSLContext context = DSL.using(jooqConfiguration.derive());
context.data("queryName", "query1");
return context.select(1).from("dual").fetch();
然后,在你的 ExecuteListener
:
@Override
public void fetchEnd(ExecuteContext ctx) {
// Reading the Configuration.data() is still fine:
Tags prometheusTag = Tags.of("queryName",
ctx.configuration().data("queryName").toString());
meterRegistry.timer("sql.query.timer", prometheusTag)
.record(watch.split(), TimeUnit.NANOSECONDS);
}
@Override
public void end(ExecuteContext ctx) {
// But you shouldn't modify it
ctx.configuration().data().remove("queryName");
}