insertar - ¿Cómo se configura el registro en Hibernate 4 para usar SLF4J?
hibernate configuration java (11)
Hibernate 3.x usó slf4j para el registro. Hibernate 4.x usa jboss-logging . Estoy escribiendo una aplicación independiente que utiliza Hibernate 4 y SLF4J para el registro.
¿Cómo puedo configurar Hibernate para que se registre en SLF4J?
Si eso no es posible, ¿cómo puedo configurar el registro de Hibernate?
La sección del manual de Hibernate 4.1 sobre el inicio de sesión comienza con la advertencia de que es ...
Completamente desactualizado Hibernate usa JBoss Logging a partir de 4.0. Esto se documentará cuando migremos este contenido a la Guía del Desarrollador.
... continúa hablando de SLF4J, y es inútil. Ni la guía de inicio ni la guía para desarrolladores hablan sobre la registración. Tampoco lo hace la guía de migración .
He buscado documentación sobre jboss-logging en sí, pero no he podido encontrar ninguno. La página de GitHub está en silencio , y la página de proyectos de la comunidad de JBoss ni siquiera muestra el registro de jboss. Me pregunté si el rastreador de errores del proyecto podría tener problemas relacionados con la provisión de documentación, pero no es así.
La buena noticia es que cuando se utiliza Hibernate 4 dentro de un servidor de aplicaciones, como JBoss AS7, el registro se ocupa en gran medida de usted. Pero, ¿cómo puedo configurarlo en una aplicación independiente?
¿Has probado esto?
- slf4j-log4j12.jar en el caso de Log4J. Consulte la documentación de SLF4J para más detalles. Para usar Log4j también necesitará colocar un archivo log4j.properties en su classpath. Un archivo de propiedades de ejemplo se distribuye con Hibernate en el directorio src /
simplemente agregue estas jarras y propiedades o log4j xml en el classpath
static final String LOGGING_PROVIDER_KEY = "org.jboss.logging.provider";
private static LoggerProvider findProvider() {
// Since the impl classes refer to the back-end frameworks directly, if this classloader can''t find the target
// log classes, then it doesn''t really matter if they''re possibly available from the TCCL because we won''t be
// able to find it anyway
final ClassLoader cl = LoggerProviders.class.getClassLoader();
try {
// Check the system property
final String loggerProvider = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(LOGGING_PROVIDER_KEY);
}
});
if (loggerProvider != null) {
if ("jboss".equalsIgnoreCase(loggerProvider)) {
return tryJBossLogManager(cl);
} else if ("jdk".equalsIgnoreCase(loggerProvider)) {
return tryJDK();
} else if ("log4j".equalsIgnoreCase(loggerProvider)) {
return tryLog4j(cl);
} else if ("slf4j".equalsIgnoreCase(loggerProvider)) {
return trySlf4j();
}
}
} catch (Throwable t) {
}
try {
return tryJBossLogManager(cl);
} catch (Throwable t) {
// nope...
}
try {
return tryLog4j(cl);
} catch (Throwable t) {
// nope...
}
try {
// only use slf4j if Logback is in use
Class.forName("ch.qos.logback.classic.Logger", false, cl);
return trySlf4j();
} catch (Throwable t) {
// nope...
}
return tryJDK();
}
Los valores posibles para org.jboss.logging.provider
son: jboss
, jdk
, log4j
, slf4j
.
Si no configura org.jboss.logging.provider
, prueba jboss, luego log4j, luego slf4j (solo si se usa logback) y repliegue a jdk.
Yo uso slf4j
con logback-classic
:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
<scope>${logging.scope}</scope>
</dependency>
y todo funciona bien!
ACTUALIZACIÓN Algunos usuarios usan en la aplicación principal.java:
static { //runs when the main class is loaded.
System.setProperty("org.jboss.logging.provider", "slf4j");
}
pero para soluciones basadas en contenedores esto no funciona.
ACTUALIZACIÓN 2 Aquellos que piensan que manejan Log4j con SLF4J para jboss-logging
no es exactamente así. jboss-logging
usa directamente Log4j sin SLF4J!
Estoy usando Hibernate Core 4.1.7.Final plus Spring 3.1.2.RELEASE en una aplicación independiente. Agregué Log4j 1.2.17 a mis dependencias y parece que, como JBoss Logging registra directamente a log4j si está disponible y Spring usa Commons Logging, que también usa Log4j si está disponible, todo el Logging podría configurarse a través de Log4J.
Aquí está mi lista de dependencias relevantes:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.7.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
Hibernate 4.3 tiene http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html sobre cómo controlar org.jboss.logging
:
Busca en la ruta de clase para un proveedor de registro . Busca slf4j después de buscar log4j. Por lo tanto, en teoría, asegúrese de que su classpath (WAR) no incluya log4j e incluya la API slf4j y un back-end debería funcionar.
Como último recurso, puede establecer la propiedad del sistema
org.jboss.logging.provider
enslf4j
.
A pesar de los reclamos de la documentación, org.jboss.logging
insistió en intentar usar log4j, a pesar de que log4j estaba ausente y que SLF4J estaba presente, lo que dio como resultado el siguiente mensaje en mi archivo de registro de Tomcat ( /var/log/tomcat/catalina.out
) :
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Tuve que seguir la sugerencia de la respuesta de dasAnderl ausMinga e incluir el puente log4j-over-slf4j
.
Inspirado por la publicación Hypoport de Leif , así es como "doblé" Hibernate 4 de regreso a slf4j:
Supongamos que estás usando Maven.
- Agregue
org.slf4j:log4j-over-slf4j
como una dependencia de supom.xml
- Usando el comando
mvn dependency:tree
, asegúrate de que ninguno de los artefactos que estás usandoslf4j:slf4j
deslf4j:slf4j
(para ser precisos, ningún artefacto debe tener una dependencia de ámbito de compilación o una dependencia de ámbito de tiempo de ejecución enslf4j:slf4j
)
Antecedentes: Hibernate 4.x tiene una dependencia en el artefacto org.jboss.logging:jboss-logging
. Transitivamente, este artefacto tiene una dependencia de alcance proporcionada en el artefacto slf4j:slf4j
.
Como ahora hemos agregado el org.slf4j:log4j-over-slf4j
, org.slf4j:log4j-over-slf4j
imita el artefacto slf4j:slf4j
. Por lo tanto, todo lo que JBoss Logging
registra ahora realmente irá a través de slf4j.
Digamos que estás usando Logback como tu back-end de registro. Aquí hay una muestra pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
....
<properties>
....
<slf4j-api-version>1.7.2</slf4j-api-version>
<log4j-over-slf4j-version>1.7.2</log4j-over-slf4j-version>
<jcl-over-slf4j-version>1.7.2</jcl-over-slf4j-version> <!-- no problem to have yet another slf4j bridge -->
<logback-core-version>1.0.7</logback-core-version>
<logback-classic-version>1.0.7</logback-classic-version>
<hibernate-entitymanager-version>4.1.7.Final</hibernate-entitymanager-version> <!-- our logging problem child -->
</properties>
<dependencies>
<!-- begin: logging-related artifacts .... -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl-over-slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${log4j-over-slf4j-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback-core-version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback-classic-version}</version>
</dependency>
<!-- end: logging-related artifacts .... -->
<!-- begin: some artifact with direct dependency on log4j:log4j .... -->
<dependency>
<groupId>org.foo</groupId>
<artifactId>some-artifact-with-compile-or-runtime-scope-dependency-on-log4j:log4j</artifactId>
<version>${bla}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- begin: some artifact with direct dependency on log4j:log4j .... -->
<!-- begin: a hibernate 4.x problem child........... -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate-entitymanager-version}</version>
</dependencies>
<!-- end: a hibernate 4.x problem child........... -->
....
</project>
En su classpath, tenga un logback.xml
, como este ubicado en src/main/java
:
<!-- begin: logback.xml -->
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.hibernate" level="debug"/>
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>
<!-- end: logback.xml -->
Es posible que algunos componentes deseen tener acceso a logback.xml
en el momento de la logback.xml
en marcha de JVM para el registro adecuado, por ejemplo, el Plugin Jetty Maven. En ese caso, agregue un sistema Java logback.configurationFile=./path/to/logback.xml
a su comando (por ejemplo, mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run
).
En caso de que todavía esté obteniendo la salida de hibernación estándar de la consola "sin procesar" (como Hibernate: select ...
), puede aplicar la pregunta de desbordamiento de pila " Desactivar el registro de hibernación en la consola ".
Para cualquiera que pudiera enfrentar el mismo problema que yo tuve. En caso de que haya probado todas las otras soluciones explicadas aquí y aún no vea que el registro de hibernación funcione con su slf4j, podría ser porque está utilizando un contenedor que tiene en su carpeta las bibliotecas el jboss-logging.jar. Esto significa que se carga previamente antes de que pueda configurar cualquier configuración para influir en ella. Para evitar este problema en weblogic puede especificar en el archivo weblogic-application.xml en su oído / META-INF para preferir la biblioteca cargada desde la aplicación. debería haber un mecanismo similar para otros contenedores de servidor. En mi caso, tuve que agregar:
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-application xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-application" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/javaee_5.xsd http://xmlns.oracle.com/weblogic/weblogic-application http://xmlns.oracle.com/weblogic/weblogic-application/1.5/weblogic-application.xsd">
<wls:prefer-application-packages>
<!-- logging -->
<wls:package-name>org.slf4j.*</wls:package-name>
<wls:package-name>org.jboss.logging.*</wls:package-name>
</wls:prefer-application-packages>
<wls:prefer-application-resources>
<wls:resource-name>org/slf4j/impl/StaticLoggerBinder.class</wls:resource-name>
</wls:prefer-application-resources>
</wls:weblogic-application>
Para que SLF4J funcione con JBoss Logging sin Logback como back-end, se requiere el uso de una propiedad del sistema org.jboss.logging.provider=slf4j
. log4j-over-slf4j
tácticas log4j-over-slf4j
no parecen estar funcionando en este caso porque el registro volverá a caer en JDK si ni Logback ni log4j realmente están presentes en classpath.
Esto es un poco molesto y para que funcione la autodetección, verá que el cargador de clases contiene al menos ch.qos.logback.classic.Logger
de logback-classic u org.apache.log4j.Hierarchy
de log4j para engañar al JBoss Logging from not falling back to JDK logging.
La magia se interpreta en org.jboss.logging.LoggerProviders
ACTUALIZACIÓN: Se agregó el soporte del cargador de servicio, por lo que es posible evitar problemas con la autodetección al declarar META-INF/services/org.jboss.logging.LoggerProvider
(con org.jboss.logging.Slf4jLoggerProvider
como valor). Parece que también se ha agregado soporte log4j2.
Primero, se da cuenta de que SLF4J no es una biblioteca de registro correcta, es un contenedor de registro. En sí mismo no registra nada, simplemente delega a "backends".
Para "configurar" el registro de jboss, simplemente agregue el marco de registro que desee usar en su classpath (junto con jboss-logging) y jboss-logging se da cuenta del resto.
Creé una guía centrada en Hibernate para la configuración de JBoss Logging: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html
Tuve un problema al hacer que hibernate 4 logging funcionara con weblogic 12c y log4j. La solución es poner lo siguiente en su weblogic-application.xml:
<prefer-application-packages>
<package-name>org.apache.log4j.*</package-name>
<package-name>org.jboss.logging.*</package-name>
</prefer-application-packages>
Yo uso maven y agregué la siguiente dependencia:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
Luego, creé un archivo log4j.properties
en /src/main/resources
:
# direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
# set log levels
log4j.rootLogger=warn
Esto lo pondrá en la raíz de tu .jar
. Funciona a las mil maravillas...
así que lo hice funcionar en mi proyecto hibernar 4, slf4j, logback. mi proyecto es gradle, pero debería ser el mismo para maven.
Básicamente, Abdull tiene razón. Donde NO tiene razón, es que NO DEBE eliminar slf4j de las dependencias.
incluir para compilar el alcance:
org.slf4j: slf4j-api
org.slf4j: log4j-over-slf4j
por ejemplo, para logback (ch.qos.logback: logback-classic, ch.qos.logback: logback-core: 1.0.12)
excluir completamente log4j libs de las dependencias
resultado: registros de hibernación a través de slf4j a logback. por supuesto, debería poder utilizar una implementación de registro diferente a la de inicio de sesión
para estar seguro de que no hay log4j presente, verifique sus libs en classpath o web-inf / lib para los archivos war.
por supuesto, ha configurado los registradores en logback.xml, por ejemplo:
<logger name="org.hibernate.SQL" level="TRACE"/>