要跟踪休眠SQL语句的参数值,常见的log4j参数化如下所示:
<logger name="org.hibernate.SQL">
<level value="debug" />
</logger>
<logger name="org.hibernate.type.descriptor.sql.BasicBinder">
<level value="trace" />
</logger>
这将产生如下日志输出:
2019-01-10 00:10:29,349 [main] DEBUG SqlStatementLogger.logStatement(SqlStatementLogger.java:92) - select land0_.fk_land as fk_land1_24_0_ from land land0_ where land0_.fk_land=?
2019-01-10 00:10:29,349 [main] TRACE BasicBinder.bind(BasicBinder.java:65) - binding parameter [1] as [BIGINT] - [27]
这对于分析运行时如何执行应用程序路径非常有用。
问题在于,BasicBinder
还记录了LOB参数值的整个字符串表示形式(例如byte[]
),这非常无用:
2019-01-07 13:28:45,466 [wwsservices-catalina-exec-10] TRACE org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [2] as [BLOB] - [[37, 80, 68, 70, 45, 49, 46, 52, ...
整个blob的字符串表示形式被打印到日志文件中,这对我来说很烦人。
有没有办法在仍然显示其他语句参数值的同时抑制/缩短Hibernate或log4j中LOB值的日志输出?
是否可以在log4j中设置最大日志语句大小?
答案 0 :(得分:2)
Hibernate 5.2.3中已解决HHH-11097个问题,该问题也可以解决您的问题:
在this commit中,BlobTypeDescriptor
(及其他)将覆盖extractLoggableRepresentation
:
@Override
public String extractLoggableRepresentation(Blob value) {
return value == null ? "null" : "BLOB{...}";
}
现在覆盖的默认实现(导致您的问题)如下所示:
@Override
public String extractLoggableRepresentation(T value) {
return (value == null) ? "null" : value.toString();
}
这应该从您的日志中删除那些巨行。
如果您使用的是最新版本的休眠模式,则很可能使用实例化blob /原始字节数组(byte[]
)。负责此操作的类型描述符是PrimitiveByteArrayTypeDescriptor,它疯狂地实现了extractLoggableRepresentation
方法,如下所示:
@Override
public String extractLoggableRepresentation(byte[] value) {
return (value == null) ? super.extractLoggableRepresentation( null ) : Arrays.toString( value );
}
在这种情况下,我看到的唯一解决方案是
UserType
:自定义UserType
必须实现nullSafeSet
并将自定义JavaTypeDescriptor
传递给进行绑定和记录的绑定器:
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
final SharedSessionContractImplementor session) throws HibernateException, SQLException {
// Simply do what
// org.hibernate.type.AbstractStandardBasicType.nullSafeSet(PreparedStatement, Object, int, WrapperOptions)
// does, but using a custom descriptor.
session.remapSqlTypeDescriptor(MaterializedBlobType.INSTANCE.getSqlTypeDescriptor())
.getBinder(CustomPrimitiveByteArrayTypeDescriptor.INSTANCE)
.bind(st, (byte[]) value, index, session);
}
自定义JavaTypeDescriptor
只是扩展了PrimitiveByteArrayTypeDescriptor
并覆盖了有问题的extractLoggableRepresentation
方法:
public class CustomPrimitiveByteArrayTypeDescriptor extends PrimitiveByteArrayTypeDescriptor {
public static final CustomPrimitiveByteArrayTypeDescriptor INSTANCE = new CustomPrimitiveByteArrayTypeDescriptor();
@Override
public String extractLoggableRepresentation(byte[] value) {
if (null == value) {
return super.extractLoggableRepresentation(value);
} else {
return "byte[" + value.length + "]";
}
}
}
答案 1 :(得分:1)
我知道这是一个老问题,但我今天遇到了这个问题,并找到了一种方法来正常记录所有类型,同时使用 log4j2 过滤器(特别是 RegexFilter)避免 blob 类型
Rc::clone(view.state_mut())
也许这对某人有用。