Para trazar valores de los parámetros de las sentencias SQL de hibernación, un log4j común de parametrización que se parece a:
<logger name="org.hibernate.SQL">
<level value="debug" />
</logger>
<logger name="org.hibernate.type.descriptor.sql.BasicBinder">
<level value="trace" />
</logger>
Este rendimientos salidas como que log:
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]
Esto es muy útil para analizar la forma en la ruta de la aplicación se ejecuta en tiempo de ejecución.
El problema es, que BasicBinder
también registra toda la representación de cadena de valores de los parámetros de línea de negocio (como byte[]
) que es muy 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, ...
La representación de cadena de toda la mancha se imprime el archivo de registro que es muy molesto para mí.
¿Hay una manera de suprimir / acortar registrar la salida de los valores LOB en hibernación o log4j mientras sigue mostrando valores de otros parámetros de la sentencia?
¿Existe la posibilidad de establecer el tamaño máximo declaración de registro en log4j?
Ha habido un problema HHH-11097 fijado para Hibernate 5.2.3 que también debería resolver su problema:
En esta confirmación , el BlobTypeDescriptor
(y otros) obtiene un reemplazo para extractLoggableRepresentation
:
@Override
public String extractLoggableRepresentation(Blob value) {
return value == null ? "null" : "BLOB{...}";
}
La implementación por defecto (que causa el problema) se ve ahora anulado como este:
@Override
public String extractLoggableRepresentation(T value) {
return (value == null) ? "null" : value.toString();
}
Esto debería eliminar esas líneas gigantes de su registro.
Si está utilizando una versión reciente de hibernación, es probable que esté utilizando materializaste blobs / matrices de bytes primitivos ( byte[]
). El descriptor de tipo responsable de esto es PrimitiveByteArrayTypeDescriptor que implementa locamente el extractLoggableRepresentation
método como este:
@Override
public String extractLoggableRepresentation(byte[] value) {
return (value == null) ? super.extractLoggableRepresentation( null ) : Arrays.toString( value );
}
Las únicas soluciones que veo en este caso son
- Informar de esto como un error
- Evitar el uso de gotas materializadas.
- Use una solución mediante la implementación de una costumbre
UserType
:
La costumbre UserType
debe implementar el nullSafeSet
y pasar una costumbre JavaTypeDescriptor
para el aglutinante que hace la unión y la explotación forestal:
@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);
}
La costumbre JavaTypeDescriptor
simplemente extiende el PrimitiveByteArrayTypeDescriptor
y anula la problemática extractLoggableRepresentation
método:
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 + "]";
}
}
}