web-dev-qa-db-ja.com

Hibernate 4でSLF4Jを使用するようにロギングを設定するにはどうすればよいですか

Hibernate 3.xは、ロギングに slf4j を使用しました。 Hibernate 4.xは jboss-logging を使用します。ロギングにHibernate 4とSLF4Jを使用するスタンドアロンアプリケーションを作成しています。

SLF4Jにログを記録するようにHibernateを構成するにはどうすればよいですか?

それが不可能な場合、Hibernateのログを設定するにはどうすればよいですか?

Hibernate 4.1マニュアル ロギングのセクション は、次のような警告で始まります...

完全に古くなっています。 Hibernateは4.0からJBoss Loggingを使用します。これは、このコンテンツを開発者ガイドに移行するときに文書化されます。

... SLF4Jについて話を続けるので、役に立たない。 入門ガイド開発者ガイド のどちらも、ロギングについてまったく話していない 移行ガイド も行いません。

Jboss-logging自体に関するドキュメントを探しましたが、まったく見つけられませんでした。 GitHubページはサイレント であり、JBossの コミュニティプロジェクトページ はjboss-loggingをリストしません。このプロジェクトの バグトラッカー にはドキュメントの提供に関連する問題があるのではないかと思いましたが、そうではありません。

良いニュースは、JBoss AS7などのアプリケーションサーバー内でHibernate 4を使用する場合、ロギングが大部分が処理されることです。しかし、スタンドアロンアプリケーションでどのように構成できますか?

111
Tom Anderson

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 2jboss-loggingのためにSLF4JでLog4jを管理していると考える人はそうではありません。 jboss-loggingはSLF4JなしでLog4jを直接使用します!

57
gavenkoa

バックエンドがシステムプロパティorg.jboss.logging.provider=slf4jを使用する必要があるため、SLF4JをLogbackなしでJBoss Loggingで動作させるには。 Logbackもlog4jもクラスパスに実際に存在しない場合、ロギングはJDKにフォールバックするため、log4j-over-slf4j戦術は機能していないようです。

これは少し面倒で、自動検出を機能させるには、クラスローダーに少なくともlogback-classicからのch.qos.logback.classic.Loggerまたはlog4jからのorg.Apache.log4j.Hierarchyが含まれており、JBoss LoggingがフォールバックしないようにしますJDKロギングへ。

魔法はorg.jboss.logging.LoggerProvidersで解釈されます

更新:サービスローダーのサポートが追加され、META-INF/services/org.jboss.logging.LoggerProvider(値としてorg.jboss.logging.Slf4jLoggerProviderを使用)を宣言することで自動検出の問題を回避できるようになりました。 log4j2のサポートも追加されたようです。

27
Tuomas Kiviaho

LeifのHypoportの投稿 に触発され、これがHibernate 4をslf4jに「曲げる」方法です。

Mavenを使用していると仮定しましょう。

  • org.slf4j:log4j-over-slf4jへの依存関係としてpom.xmlを追加します
  • コマンドmvn dependency:treeを使用して、使用しているアーティファクトのnoneslf4j:slf4jに依存していることを確認してください(正確には、noアーティファクトには、slf4j:slf4jに対してcompileスコープ依存関係またはruntimeスコープ依存関係が必要です。

背景:Hibernate 4.xは、アーティファクトorg.jboss.logging:jboss-loggingに依存しています。推移的に、このアーティファクトには、アーティファクトslf4j:slf4jに対するprovidedスコープ依存関係があります。

org.slf4j:log4j-over-slf4jアーティファクトを追加したので、org.slf4j:log4j-over-slf4jslf4j: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>

クラスパスで、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 -->

Jetty Mavenプラグインなど、一部のコンポーネントは、適切なロギングのためにJVMの起動時にlogback.xmlへのアクセスを必要とする場合があります。その場合は、Java system logback.configurationFile=./path/to/logback.xmlをコマンドに追加します(例:mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run)。

まだ「raw」コンソールstdout Hibernate出力(Hibernate: select ...など)を取得している場合は、スタックオーバーフローの質問 " コンソールへのhibernateロギングをオフにする "が適用される場合があります。

12
Abdull

まず、SLF4Jはロギングライブラリの権利ではなく、ロギングラッパーであることを理解します。それ自体は何もログに記録せず、単に「バックエンド」に委任します。

Jboss-loggingを「設定」するには、クラスパスで使用する任意のログフレームワークを(jboss-loggingとともに)追加するだけで、jboss-loggingは残りを計算します。

JBossロギング設定のHibernateに焦点を当てたガイドを作成しました: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

9
Steve Ebersole

スタンドアロンアプリでHibernate Core 4.1.7.FinalとSpring 3.1.2.RELEASEを使用しています。 Log4j 1.2.17を依存関係に追加しました。JBossLoggingが利用可能な場合はlog4jに直接ログを記録し、SpringはCommons Loggingを使用し、利用可能な場合はwitchも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>
3
Stefan Scheidt

Hibernate 4.3には、 一部のドキュメントorg.jboss.loggingの制御方法に関するものがあります。

  • ロギングプロバイダーのクラスパスを検索します。 log4jを検索した後、slf4jを検索します。したがって、理論的には、クラスパス(WAR)にlog4jが含まれず、slf4j APIが含まれていることを確認し、バックエンドが機能するようにします。

  • 最後の手段として、org.jboss.logging.providerシステムプロパティをslf4jに設定できます。


ドキュメントの主張にもかかわらず、org.jboss.loggingはlog4jが存在せずSLF4Jが存在するにもかかわらず、log4jを使用しようと主張し、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ブリッジを含める必要がありました。

3
Raedwald

だから、ちょうど私のプロジェクトで動作するようになりました。 hibernate 4、slf4j、ログバック。私のプロジェクトはgradleですが、mavenでも同じである必要があります。

基本的に、Abdullは正しい。彼が正しくない場合、依存関係からslf4jを削除する必要はありません。

  1. スコープのコンパイルに含める:

    org.slf4j:slf4j-api

    org.slf4j:log4j-over-slf4j

    例えばログバック用(ch.qos.logback:logback-classic、ch.qos.logback:logback-core:1.0.12)

  2. log4jライブラリを依存関係から完全に除外します

結果:休止状態はslf4jを介してログバックします。もちろん、logbackとは異なるログ実装を使用できるはずです。

log4jが存在しないことを確認するには、クラスパスまたはweb-inf/libのlibでwarファイルを確認します。

もちろん、logback.xmlでロガーを設定しています。 :

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

2

私はmavenを使用し、次の依存関係を追加しました。

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

次に、log4j.properties/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

これにより、.jarのルートに配置されます。それは魅力のように機能します...

2

Weblogic 12cおよびlog4jでhibernate 4ロギングを動作させる際に問題が発生しました。解決策は、weblogic-application.xmlに次を追加することです。

<prefer-application-packages>
    <package-name>org.Apache.log4j.*</package-name>
    <package-name>org.jboss.logging.*</package-name>
</prefer-application-packages>
1
gozer

私が抱えていた同じ問題に直面する可能性のある人に。ここで説明する他のすべてのソリューションを試しても、slf4jで休止状態ログが機能しない場合は、フォルダーライブラリに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>
0
Massimo