2012-07-24 40 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>