Reputation: 1105
To trace parameter values of hibernate SQL statements, a common log4j parametrization looks like that:
<logger name="org.hibernate.SQL">
<level value="debug" />
</logger>
<logger name="org.hibernate.type.descriptor.sql.BasicBinder">
<level value="trace" />
</logger>
This yields log outputs like that:
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]
This is very useful to analyze how the application path was executed at runtime.
The problem is, that BasicBinder
also logs the whole string representation of values of LOB parameters (like byte[]
) which is very unuseful:
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, ...
The string representation of the whole blob is printed to the log file which is very annoying to me.
Is there a way to suppress / shorten log output of LOB values in Hibernate or log4j while still displaying values of other statement parameters?
Is there a possibility to set maximum log statement size in log4j?
Upvotes: 6
Views: 1621
Reputation: 21
I know this is an old question but I was having this problem today and found a way to log all types normally while avoiding the blob type using log4j2 filters, specifically a RegexFilter
<AsyncLogger name="org.hibernate.type.descriptor.sql" level="trace" additivity="false">
<RegexFilter regex=".*[BLOB].*" onMatch="DENY" onMismatch="NEUTRAL"/>
<AppenderRef ref="Console"/>
<AppenderRef ref="File" />
</AsyncLogger>
Maybe this will be usefull to someone.
Upvotes: 2
Reputation: 6184
There has been an issue HHH-11097 fixed for Hibernate 5.2.3 which should also solve your problem:
In this commit, the BlobTypeDescriptor
(and others) gets an override for extractLoggableRepresentation
:
@Override
public String extractLoggableRepresentation(Blob value) {
return value == null ? "null" : "BLOB{...}";
}
The default implementation (causing your issue) now overridden looks like this:
@Override
public String extractLoggableRepresentation(T value) {
return (value == null) ? "null" : value.toString();
}
This should remove those giant lines from your log.
If you are using a recent version of hibernate, you are likely using materialized blobs / primitive byte arrays (byte[]
). The type descriptor responsible for this is PrimitiveByteArrayTypeDescriptor which madly implements the extractLoggableRepresentation
method like this:
@Override
public String extractLoggableRepresentation(byte[] value) {
return (value == null) ? super.extractLoggableRepresentation( null ) : Arrays.toString( value );
}
The only solutions I see in this case are
UserType
:The custom UserType
must implement the nullSafeSet
and pass a custom JavaTypeDescriptor
to the binder which does the binding and logging:
@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);
}
The custom JavaTypeDescriptor
simply extends the PrimitiveByteArrayTypeDescriptor
and overrides the problematic extractLoggableRepresentation
method:
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 + "]";
}
}
}
Upvotes: 6