SLF4Jを使用するようにHibernate 4でロギングを構成するには


114

使用されているHibernate 3.x ロギング用。Hibernate 4.xは。ロギングにHibernate 4とSLF4Jを使用するスタンドアロンアプリケーションを書いています。

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

それが不可能な場合、どうすればHibernateのロギングを構成できますか?

ロギングに関する Hibernate 4.1マニュアルのセクションは、それが...であるという警告で始まります。

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

... SLF4Jについて話し続けるので、役に立たない。入門ガイド開発者ガイドも、ロギングについてはまったく触れていません。移行ガイドも同様です。

jboss-logging自体のドキュメントを探しましたが、何も見つけることができませんでした。GitHubのページは沈黙している、とJBossのコミュニティプロジェクトのページには、でも、リストのjboss-ロギングを行いません。プロジェクトのバグトラッカーにドキュメントの提供に問題があるのではないかと思いましたが、実際はそうではありませんでした。

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


13
ロギングに関するHibernateドキュメントが古いことを強調するための+1
mhnagaoka 2013年

システムプロパティorg.jboss.logging.provide = slf4jを設定できます。詳細については、リンクdocs.jboss.org/hibernate/orm/4.3/topical/html/logging/…を参照してください。Hibernateバージョンが3以降の場合
Abhishek Ranjan

回答:


60

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へのフォールバックが試行されます。

私はslf4jと一緒に使用しlogback-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 Log4jをSLF4Jで管理していると考える人は、必ずしもそうjboss-loggingではありません。jboss-loggingSLF4JなしでLog4jを直接使用します!


1
どこに設定しorg.jboss.logging.providerますか?
Suzan Cioc 2014年

1
@SuzanCiocによると、System.getProperty(LOGGING_PROVIDER_KEY);システムプロパティを設定する必要があります。スルーjava -D...=...かは、あなたのコンテナのドキュメントを確認してください。
ジヴェンコア2014年

1
slf4jを介してlog4jを使用できないという2つ目の更新は役に立ちました。org.jboss.logging.providerをslf4jに設定すると、log4jのバッキングが有効になると思いましたが、そうではありませんでした。これを機能させるには、直接log4jに設定する必要がありました。奇数。この構成のオプションとしてのslf4jのポイントは何ですか?
Travis Spencer

27

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

これは少し厄介で、自動検出を機能させるために、クラスローダーに少なくともch.qos.logback.classic.Loggerlogback-classicまたはorg.apache.log4j.Hierarchylog4j が含まれており、JBoss LoggingがJDKロギングにフォールバックしないように仕向けていることがわかります。

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

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


1
このシステムプロパティはどこに設定しますか?
jhegedus 14年

設定にもよりますが、通常はコマンドラインスイッチ-Dorg.jboss.logging.provider=slf4jで十分です。LoggingProviders.javaは、現在受け入れられている値と、クラスパスに存在すると予想されるものについてのより良い洞察を提供します。
Tuomas Kiviaho 2014

2
クラスでSlf4jLoggerProviderはないため、サービスローダーアプローチは機能しないと思いますpublicか?
holmis83 2016年

weblogic WARのorg.jboss.logging.providerをソースコードに設定する必要がありますが、静的クラス初期化子はLoggingProvidersの後に呼び出されます!
Antonio Petricca

12

LeifのHypoport投稿に触発されて、Hibernate 4をslf4jに「曲げ」ました。

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

  • org.slf4j:log4j-over-slf4j依存関係として追加しますpom.xml
  • コマンドを使用してmvn dependency:tree、確認していない何もあなたが上dependeを使用しているアーティファクトのをslf4j: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 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 -->

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

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


1
他のライブラリがlog4jを含まないことを確認してください。例:activemq-all.jarにはlog4jが含まれています。ヒント:IDEを開いて、コード内で簡単にlog4jを見つけてください。
Dimitri Dewaele 2013年

JBoss Hibernate4と(あまりに)古いサーバーでこの問題が発生しました。application.propertiesの1行を含むこの投稿は私にとってはうまくいきました。だからTNX !!! そして、私のプロパティの最後の行は、ここの別の回答で書かれました:org.jboss.logging.provider=slf4j
Jeroen van Dijk-Jun

8

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

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

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


2
はい、SLF4Jがファサードであることは確かです。HibernateロギングをSLF4Jに送信するということは、残りのアプリケーション用に選択したバックエンドに到達することを意味します。
トムアンダーソン

10
だからあなたが設定について言っていることは、設定がない(それはいいです!)ということですが、jboss-loggingは何とかバックエンドを検出して選択しますか?ああ、今私は実際にコードを見るのに時間をかけています、それがまさに何が起こるかわかります。具体的には、jboss-loggingは、JBoss LogManager、log4j、SLF4Jを介したLogback、JDKロギングの順に試行します。ただし、これはシステムプロパティでオーバーライドできorg.jboss.logging.providerます。
トムアンダーソン

2
私たちの多くは、コモンズログによって物事を把握しているため、jbossログがどのように機能するかを正確に知ることは、予期しない事態が発生したときに現実の世界でそれをサポートできるようにするために重要です。
ams

1
上記のリンクは、実際にそれがあなたが本当に見たいものである場合に何が起こるかを正確に示しているので、フォローしないでください...
Steve Ebersole '13

3

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

だから、私のプロジェクトでそれを機能させました。hibernate 4、slf4j、logback。私のプロジェクトはGradleですが、Mavenでも同じです。

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

  1. スコープをコンパイルするために含める:

    org.slf4j:slf4j-api

    org.slf4j:log4j-over-slf4j

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

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

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

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

もちろん、logback.xmlにロガーを設定しました。例:

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


この正確な問題がありました。log4jは、別のライブラリからの推移的な依存関係として取り込まれていました。それを除外すると、logbackとslf4j log4jブリッジを使用して、休止状態のロギングが期待どおりに機能し始めました
Paul Zepernick

3

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ブリッジを含める必要がありました。


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。それは魅力のように機能します...


3
これにより、log4jの使用が構成されます。OPはlog4jを使用したくない。彼らはslf4jを使いたいと思っています。
Raedwald 2014

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 Loggingが表示されない場合は、彼のフォルダーライブラリーに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>

-2

これを試しましたか:

-Log4Jの場合はslf4j-log4j12.jar。詳細については、SLF4Jのドキュメントを参照してください。Log4jを使用するには、log4j.propertiesファイルをクラスパスに配置する必要もあります。プロパティファイルの例は、Hibernateとともにsrc /ディレクトリに配布されています。

これらのjarとプロパティまたはlog4j xmlをクラスパスに追加するだけです


4
これは、Hibernate 3.xドキュメントからの引用です。SLF4Jを使用しないHibernate 4.xでも引き続き機能すると思いますか?
トムアンダーソン

私が覚えている限り、log4jで十分です
アビハイマルチャーノ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.