如何在Hibernate 4中configuration日志来使用SLF4J

Hibernate 3.x使用slf4j进行日志logging。 Hibernate 4.x使用jboss日志logging 。 我正在编写一个使用Hibernate 4和SLF4J进行日志logging的独立应用程序。

我如何configurationHibernatelogin到SLF4J?

如果这是不可能的,我怎么configurationHibernate的日志?

日志logging的Hibernate 4.1手动部分的启动警告,它是…

完全过时。 Hibernate从4.0开始使用JBoss Logging。 当我们将这些内容迁移到开发者指南时,这将被logging。

…继续谈SLF4J,所以没用。 入门指南和开发者指南都没有谈及日志logging。 迁移指南也不是。

我已经查找了jboss日志本身的文档,但是我一直没能find任何东西。 GitHub页面是沉默的 ,JBoss的社区项目页面甚至没有列出jboss日志logging。 我想知道该项目的bug跟踪器是否可能有任何与提供文档有关的问题,但事实并非如此。

好消息是,当在一个应用服务器(如JBoss AS7)中使用Hibernate 4时,日志logging很大程度上为您处理。 但是我怎样才能configuration它在一个独立的应用程序?

请看https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/org/jboss/logging/LoggerProviders.java

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(); } 

所以org.jboss.logging.provider可能的值是: jbossjdklog4jslf4j

如果你没有设置org.jboss.logging.provider它会尝试jboss,然后是log4j,然后是slf4j(只有在使用了logback的情况下)并回退到jdk。

我使用slf4jlogback-classic

  <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.13</version> <scope>${logging.scope}</scope> </dependency> 

和一切工作正常!

更新一些用户在非常主要的App.java中使用:

 static { //runs when the main class is loaded. System.setProperty("org.jboss.logging.provider", "slf4j"); } 

但对于基于容器的解决scheme,这是行不通的。

更新2那些认为他们使用SLF4J来pipe理Log4j以进行jboss-logging的人并不完全是这样。 jboss-logging直接使用Log4j而不使用SLF4J!

为了使SLF4J能够在没有Logback的情况下使用JBoss Logging作为后端,需要使用系统属性org.jboss.logging.provider=slf4jlog4j-over-slf4j策略在这种情况下似乎不起作用,因为如果Logback和log4j在类path中都不存在,日志logging将回退到JDK。

这是有点麻烦,为了让自动检测工作,你已经看到类加载器至less包含logback-classic的ch.qos.logback.classic.Logger或者log4j的org.apache.log4j.Hierarchy 。 JBoss从不回退到JDK日志logging。

这个魔法是在org.jboss.logging.LoggerProviders解释的

更新:已添加服务加载器支持,所以可以通过声明META-INF/services/org.jboss.logging.LoggerProvider (以org.jboss.logging.Slf4jLoggerProvider作为值)来避免自动检测问题。 似乎也增加了支持log4j2。

受Leif的Hypoport的启发,这就是我如何将Hibernate 4“弯曲”回到slf4j:

假设您正在使用Maven。

  • org.slf4j:log4j-over-slf4j作为依赖项添加到您的pom.xml
  • 使用命令mvn dependency:tree ,确保所使用的构件都不 mvn dependency:treeslf4j:slf4j (具体而言,没有构件对slf4j:slf4j具有编译范围依赖或运行时范围依赖)

背景:Hibernate 4.x依赖于工件org.jboss.logging:jboss-logging 。 在传递上,这个工件具有对工件slf4j:slf4j 提供的作用域依赖。

正如我们现在添加了org.slf4j:log4j-over-slf4j工件, org.slf4j:log4j-over-slf4j模仿了slf4j:slf4j工件。 因此, JBoss Logginglogging现在实际上通过slf4j去执行。

假设您使用Logback作为日志后端。 这是一个示例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> 

在你的类path上,有一个logback.xml ,例如位于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 --> 

某些组件可能希望在JVM启动时访问logback.xml以进行正确的日志logging,例如Jetty Maven插件。 在这种情况下,将Java系统logback.configurationFile=./path/to/logback.xml到您的命令(例如, mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run )。

如果你仍然得到“原始”控制台stdout Hibernate的输出(如Hibernate: select ... ),然后堆栈溢出问题“ closureshibernate日志到控制台 ”可能适用。

首先你会意识到SLF4J不是一个日志库,它是一个日志包装器。 它本身不logging任何东西,只是委托给“后端”。

为了“configuration”jboss-logging,你只需要在你的类path中添加你想要使用的任何日志框架(以及jboss日志logging)和jboss日志logging数字。

我为JBoss Loggingconfiguration创build了一个基于Hibernate的指南: http : //docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

我正在使用Hibernate核心4.1.7.Final加Spring 3.1.2.RELEASE在一个独立的应用程序。 我添加Log4j 1.2.17到我的依赖,看来,因为JBoss日志直接logging到log4j(如果可用的话),并且Spring使用Commons Logging,如果可用的话也使用Log4j,所有Logging可以通过Log4Jconfiguration。

这是我的相关依赖列表:

 <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有一些关于如何控制org.jboss.logging 文档 :

  • 它在类path中search日志logging提供程序 。 它searchlog4j后searchslf4j。 因此,从理论上讲,确保你的类path(WAR)不包含log4j,并包含slf4j API,后端应该可以工作。

  • 作为最后的手段,您可以将org.jboss.logging.provider系统属性设置为slf4j


尽pipe有文档声明, org.jboss.logging坚持尝试使用log4j,尽pipelog4j不存在,SLF4J也存在,导致在我的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. 

我不得不按照dasAnderl ausMinga的build议回答,包括log4j-over-slf4j桥。

我使用maven并添加了以下依赖项:

 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.6</version> </dependency> 

然后,我在/src/main/resources创build了一个log4j.properties文件:

 # 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 

这将把它放在你的.jar的根目录下。 它像一个魅力…

所以,只是让我的项目工作。 hibernate 4,slf4j,logback。 我的项目是gradle,但是对于maven应该是一样的。

基本上Abdull是对的。 他不对的地方是,你不必从依赖关系中删除slf4j。

  1. 包括编译范围:

    org.slf4j:SLF4J的API

    org.slf4j:log4j的环比SLF4J

    例如logback(ch.qos.logback:logback-classic,ch.qos.logback:logback-core:1.0.12)

  2. 完全从依赖关系中排除log4j库

结果:hibernate通过slf4jlogin到logback。 当然你应该可以使用不同于logback的日志实现

要确保没有log4j存在,检查你的libs在classpath或web-inf / lib的war文件。

当然你已经在logback.xml中设置了logging器,例如:

<logger name="org.hibernate.SQL" level="TRACE"/>

我有一个问题,使得使用weblogic 12c和log4j进行hibernate 4日志logging工作。 解决scheme是将以下内容放在weblogic-application.xml中:

 <prefer-application-packages> <package-name>org.apache.log4j.*</package-name> <package-name>org.jboss.logging.*</package-name> </prefer-application-packages> 

你试过这个:

– 在Log4J的情况下,slf4j-log4j12.jar。 有关更多详细信息,请参阅SLF4J文档。 要使用Log4j,还需要在类path中放置一个log4j.properties文件。 一个示例属性文件在src /目录下与Hibernate一起分发

只需在类path中添加这些jar和属性或log4j xml即可