2012-07-24 100 views
100

Hibernate 3.x使用进行日志记录。休眠4.x使用。我正在编写一个使用Hibernate 4和SLF4J进行日志记录的独立应用程序。如何在Hibernate 4中配置日志以使用SLF4J

我如何配置Hibernate登录到SLF4J?

如果这是不可能的,我怎么配置Hibernate的日志呢?

Hibernate的4.1手动section on logging开始与警告说,这是......

完全过时了。 Hibernate从4.0开始使用JBoss Logging。这将在我们将此内容迁移到开发人员指南时得到记录。

...继续谈SLF4J,所以没用。 getting started guidedeveloper guide都没有谈论过日志记录。 migration guide也不是。

我已经看过了JBoss的日志记录的一些文档,但我一直没能找到任何人在所有。 GitHub page is silent和JBoss的community projects page甚至没有列出jboss日志记录。我想知道该项目的bug tracker是否可能存在与提供文档相关的任何问题,但事实并非如此。

的好消息是,使用Hibernate 4的应用服务器,例如JBoss AS7内部时,记录主要是采取为你照顾。但是,我怎样才能在独立的应用程序中配置它?

+12

+1突出显示日志记录Hibernate的文档已经过时 – mhnagaoka 2013-10-29 17:48:14

回答

-2

你试试这个:

- SLF4J-log4j12.jar Log4J中的情况。有关更多详细信息,请参阅SLF4J文档。要使用Log4j,您还需要在类路径中放置一个log4j.properties文件。一个例子属性文件在src /目录中与Hibernate分布式

只是在classpath

+4

这是从Hibernate 3.x的文档报价的。你认为这仍然可以与不使用SLF4J的Hibernate 4.x一起使用吗? – 2012-07-24 23:03:54

+0

据我记得log4j就够了 – 2012-07-25 03:38:07

7

首先,你一定要明白,SLF4J添加这些罐子和属性或log4j的XML是不是一个日志库的权利,它是一个记录包装。它本身不记录任何东西,它只是委托给“后端”。

的“配置”的jboss-记录你只需要添加你想在你的classpath(与JBoss的日志记录)和jboss-记录的数字出来,其余使用任何日志框架。

我创建了一个Hibernate为重点引导到JBoss日志记录配置:http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

+1

我意识到SLF4J是立面,是的。发送Hibernate日志记录到SLF4J意味着它结束在我为应用程序的其余部分选择的后端,这正是我想要的。 – 2012-07-25 07:29:13

+10

所以你说的配置是没有配置(这很好!),但是jboss-logging以某种方式检测并选择了一个后端?啊,现在我花时间看看代码,我发现[确切发生了什么](https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/组织/ JBoss的/日志/ LoggerProviders.java#L37)。具体来说,jboss日志记录按顺序尝试JBoss LogManager,log4j,通过SLF4J的Logback和JDK日志记录。但是这个*可以被'org.jboss.logging.provider'系统属性覆盖。 – 2012-07-25 07:33:50

+2

我们中的很多人都被公共日志记录数据烧毁了,因此了解jboss日志记录的工作方式对于在意外事件发生时能够在现实世界中支持它至关重要。 – ams 2012-08-12 20:31:35

2

我用maven,并添加以下依赖:

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

然后,我在/src/main/resources创建一个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的根源。它的工作原理就像一个魅力...

+1

这配置使用log4j。 OP不想使用log4j;他们想使用slf4j。 – Raedwald 2014-12-11 17:27:42

3

我使用Hibernate的核心4.1.7.Final加春3.1.2.RELEASE在一个独立的应用程序。我添加了Log4j 1.2。17到我的依赖关系,看起来,因为JBoss日志记录直接记录到log4j(如果可用),并且Spring使用Commons Logging,如果可用的话也使用Log4j,所有日志记录可以通过Log4J配置。

这里是我的相关依赖的名单:

<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> 
11

通过Leif's Hypoport post的启发,这是怎么了我“弯曲”休眠4回SLF4J:

让你使用Maven承担。

  • 作为依赖添加org.slf4j:log4j-over-slf4jpom.xml
  • 使用命令mvn dependency:tree,确保没有你使用上slf4j:slf4j depende文物的(准确地说,没有神器应有编译范围依赖或上slf4j:slf4j运行时范围依赖性)

背景:休眠4。 x对神器org.jboss.logging:jboss-logging有依赖性。在传递上,这个神器具有提供的范围依赖于神器slf4j:slf4j

正如我们现在已经添加了org.slf4j:log4j-over-slf4j神器,org.slf4j:log4j-over-slf4j模仿了slf4j:slf4j神器。因此,所有JBoss Logging日志现在实际上将通过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> 

在classpath中,有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用于正确的日志记录,例如Jetty Maven插件。在这种情况下,请将Java系统logback.configurationFile=./path/to/logback.xml添加到您的命令中(例如mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run)。

如果你仍然得到“原始”控制台stdout Hibernate输出(如Hibernate: select ...),那么堆栈溢出问题“Turn off hibernate logging to console”可能适用。

+1

确保没有其他图书馆icludes log4j,否则这将无法正常工作。例如:activemq-all.jar包含log4j。提示:打开IDE并在代码中轻松找到log4j。 – 2013-10-22 08:34:22

+0

我有JBoss Hibernate4和(太)旧服务器的这个问题。这篇文章,包括application.properties中的1行为我做了窍门。所以TNX!而我的属性中的最后一行是在另一个答案写在这里:'org.jboss.logging.provider = slf4j' – 2017-04-18 11:27:36

24

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

这是一个有点讨厌的,为了得到自动检测到工作,你必须看到的是,类加载器包含的logback经典或org.apache.log4j.Hierarchy从log4j的,从没有回落到JDK日志欺骗了JBoss记录至少ch.qos.logback.classic.Logger

魔术被解释在org.jboss.logging.LoggerProviders

UPDATE:服务装载机支持已被添加,从而有可能通过声明META-INF/services/org.jboss.logging.LoggerProvider(具有org.jboss.logging.Slf4jLoggerProvider作为值),以避免与自动检测的问题。似乎还增加了对log4j2的支持。

+1

我在哪里设置此系统属性? – jhegedus 2014-03-11 13:43:25

+0

取决于您的设置,但通常命令行开关'-Dorg.jboss.logging.provider = slf4j'就足够了。 [LoggingProviders.java](https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/org/jboss/logging/LoggerProviders.java)可让您更好地了解当前接受的值是预期在类路径中出现的值。 – 2014-09-10 05:24:31

+2

我不认为服务加载器方法的工作原理是因为'Slf4jLoggerProvider'不是'public'类? – holmis83 2016-03-14 13:14:24

2

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

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

  1. 包括编译范围:

    org.slf4j:SLF4J-API

    org.slf4j:log4j的-过SLF4J

    例如对的logback(ch.qos.logback:的logback经典,ch.qos.logback:的logback芯:1.0.12)

  2. 完全排除从依赖

结果log4j的库:通过冬眠日志slf4j登录。 当然你应该能够使用不同的日志实现比logback

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

当然,您已经在logback.xml中设置了记录器,例如:

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

49

查找到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> 

,所有做工精细!

UPDATE有些用户使用非常主要App.java:

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

但基于容器的解决方案,这是没有奏效。

UPDATE 2那些认为他们用SLF4J管理Log4j jboss-logging的人并不完全如此。 jboss-logging直接使用没有SLF4J的Log4j!

+1

在哪里设置org.jboss.logging.provider? – 2014-11-23 20:27:45

+1

@SuzanCioc根据System.getProperty(LOGGING_PROVIDER_KEY);'你需要设置系统属性。通过'java -D ... = ...'或检查你的容器的文档。 – gavenkoa 2014-11-24 09:21:00

+0

你的第二个更新关于不能通过slf4j使用log4j是有帮助的。将org.jboss.logging.provider设置为slf4j使我认为我对log4j的支持将会启动。但它并没有。我必须将其直接设置为log4j才能运行。奇。那么slf4j作为这个配置的选项有什么意义呢? – 2016-04-16 08:36:49

3

的Hibernate 4.3有some documentation有关如何控制org.jboss.logging

  • 它搜索类路径的日志提供商。搜索log4j后搜索slf4j。所以,理论上,确保你的类路径(WAR)不包含log4j,并包含slf4j API和后端应该工作。

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


尽管文件的要求,org.jboss.logging坚持尝试使用log4j的,尽管log4j的缺席和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的答案建议,并包括log4j-over-slf4j桥。

1

我有一个问题让hibernate 4使用weblogic 12c和log4j进行日志记录。解决方法是在weblogic-application.xml中添加以下内容:

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

对于任何可能面临同样问题的人,我都有。如果您尝试了所有其他解决方案,并且仍然没有看到与slf4j一起使用的hibernate日志记录,那可能是因为您正在使用其文件夹库中包含jboss-logging.jar的容器。这意味着在您甚至可以设置任何配置来影响它之前,它都会被预加载。 要避免weblogic中出现此问题,您可以在ear/META-INF的文件weblogic-application.xml中指定更喜欢从应用程序加载的库。其他服务器容器应该有类似的机制。 在我来说,我不得不补充:

<?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>