示例:记录缩写的绑定值
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
当实现一个 logger 时,需要仔细评估应该在哪个 logger 级别上公开多少信息。在 log4j 和类似的框架中,我们区分 FATAL、ERROR、WARN、INFO、DEBUG 和 TRACE。在 DEBUG 级别,jOOQ 的 内部默认 logger 记录所有已执行的语句,包括内联绑定值,如下所示
Executing query : select * from "BOOK" where "BOOK"."TITLE" like ? -> with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'How I stopped worrying%'
但是文本或二进制绑定值可能会变得很长,很快就会用不相关的信息填充你的日志文件。如果能够缩写这些长值(并可能在记录的语句中添加注释),那将会很好。我们可以只在 logger 实现中转换 SQL 语句,从而干净地分离关注点,而不是修补 jOOQ 的内部结构。这可以通过以下 VisitListener 来完成
// This listener is inserted into a Configuration through a VisitListenerProvider that creates a
// new listener instance for every rendering lifecycle
public class BindValueAbbreviator implements VisitListener {
private boolean anyAbbreviations = false;
@Override
public void visitStart(VisitContext context) {
// Transform only when rendering values
if (context.renderContext() != null) {
QueryPart part = context.queryPart();
// Consider only bind variables, leave other QueryParts untouched
if (part instanceof Param<?>) {
Param<?> param = (Param<?>) part;
Object value = param.getValue();
// If the bind value is a String (or Clob) of a given length, abbreviate it
// e.g. using commons-lang's StringUtils.abbreviate()
if (value instanceof String && ((String) value).length() > maxLength) {
anyAbbreviations = true;
// ... and replace it in the current rendering context (not in the Query)
context.queryPart(val(abbreviate((String) value, maxLength)));
}
// If the bind value is a byte[] (or Blob) of a given length, abbreviate it
// e.g. by removing bytes from the array
else if (value instanceof byte[] && ((byte[]) value).length > maxLength) {
anyAbbreviations = true;
// ... and replace it in the current rendering context (not in the Query)
context.queryPart(val(Arrays.copyOf((byte[]) value, maxLength)));
}
}
}
}
@Override
public void visitEnd(VisitContext context) {
// If any abbreviations were performed before...
if (anyAbbreviations) {
// ... and if this is the top-level QueryPart, then append a SQL comment to indicate the abbreviation
if (context.queryPartsLength() == 1) {
context.renderContext().sql(" -- Bind values may have been abbreviated");
}
}
}
}
如果 maxLength 设置为 5,则上面的 listener 将生成以下日志输出
Executing query : select * from "BOOK" where "BOOK"."TITLE" like ? -> with bind values : select * from "BOOK" where "BOOK"."TITLE" like 'Ho...' -- Bind values may have been abbreviated
从 jOOQ 3.3 开始,上面的 VisitListener 位于 org.jooq.tools.LoggerListener 中。
反馈
您对此页面有任何反馈吗? 我们很乐意听到您的声音!