可用版本:Dev (3.21) | 最新 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

示例:记录缩写的绑定值

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

当实现一个 logger 时,需要仔细评估应该在哪个 logger 级别上公开多少信息。在 log4j 和类似的框架中,我们区分 FATALERRORWARNINFODEBUGTRACE。在 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 中。

反馈

您对此页面有任何反馈吗? 我们很乐意听到您的声音!

The jOOQ Logo