示例:记录缩写的绑定值
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
当实现一个 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
中。
反馈
您对此页面有任何反馈吗? 我们很乐意听到您的声音!