如何在Hibernate 4中配置日志记录以使用SLF4J

Tom*_*son 111 logging hibernate slf4j hibernate-4.x jboss-logging

Hibernate 3.x使用进行日志记录.Hibernate 4.x使用.我正在编写一个独立的应用程序,它使用Hibernate 4和SLF4J进行日志记录.

如何配置Hibernate以登录SLF4J?

如果那不可能,我怎么能配置Hibernate的日志记录呢?

关于日志记录的Hibernate 4.1手册部分首先警告它是......

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

......继续谈论SLF4J,所以没用.入门指南开发人员指南都没有谈论记录.迁移指南也没有.

我已经查找了有关jboss-logging本身的文档,但我根本找不到任何文档.在GitHub的页面是沉默的,和JBoss的社区项目页面甚至没有列出的jboss-记录.我想知道项目的bug跟踪器是否可能有任何与提供文档相关的问题,但事实并非如此.

好消息是,在应用程序服务器(如JBoss AS7)中使用Hibernate 4时,很大程度上会记录日志记录.但是我如何在独立应用程序中配置它?

gav*_*koa 58

请访问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();
}
Run Code Online (Sandbox Code Playgroud)

因此,对于可能的值org.jboss.logging.provider是:jboss,jdk,log4j,slf4j.

如果你没有设置 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>
Run Code Online (Sandbox Code Playgroud)

一切正常!

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

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

但对于基于容器的解决方案,这是行不通的.

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


Tuo*_*aho 27

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

这有点令人讨厌,为了使自动检测能够工作,你已经看到类加载器至少包含ch.qos.logback.classic.Loggerlogback-classic或者org.apache.log4j.Hierarchylog4j,以使JBoss Logging不再回退到JDK日志记录.

神奇的解释是 org.jboss.logging.LoggerProviders

更新:已添加服务加载程序支持,因此可以通过声明META-INF/services/org.jboss.logging.LoggerProvider(org.jboss.logging.Slf4jLoggerProvider作为值)来避免自动检测出现问题.似乎还增加了对log4j2的支持.

  • 我不认为服务加载器方法有效,因为`Slf4jLoggerProvider`不是`public`类? (2认同)

Abd*_*ull 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>
Run Code Online (Sandbox Code Playgroud)

在你的类路径上,有一个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 -->
Run Code Online (Sandbox Code Playgroud)

某些组件可能希望能够logback.xml在JVM启动时访问正确的日志记录,例如Jetty Maven插件.在这种情况下,logback.configurationFile=./path/to/logback.xml请在命令中添加Java系统(例如mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run).

如果你仍然得到"原始"控制台stdout Hibernate输出(如Hibernate: select ...),那么Stack Overflow问题" 关闭hibernate日志记录到控制台 "可能适用.


Ste*_*ole 8

首先你意识到SLF4J不是一个正确的日志库,它是一个日志包装器.它本身不会记录任何内容,它只是委托"后端".

要"配置"jboss-logging,你只需在类路径中添加你想要使用的任何日志框架(以及jboss-logging),然后jboss-logging计算出其余部分.

我创建了一个专注于Hibernate的JBoss Logging配置指南:http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

  • 所以你所说的配置是没有配置(这很好!),但jboss-logging会以某种方式检测并选择后端?啊,现在我花时间实际查看代码,我看到的是[确实发生了什么](https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/组织/ JBoss的/日志/ LoggerProviders.java#L37).具体来说,jboss-logging按顺序尝试JBoss LogManager,log4j,通过SLF4J进行Logback和JDK日志记录.但是**可以用`org.jboss.logging.provider`系统属性覆盖. (10认同)
  • 我确实意识到SLF4J是一个外观,是的。将Hibernate日志发送到SLF4J意味着它最终会在我为应用程序其余部分选择的任何后端上完成,这正是我想要的。 (2认同)
  • 我们中的许多人都被公共资源烧毁 - 日志记录为你找到了一些东西,因此了解jboss-logging的工作方式对于在意外情况下能够在现实世界中支持它是至关重要的. (2认同)

Avi*_*ano -3

你试过这个吗:

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

只需在类路径中添加这些 jar 和属性或 log4j xml

  • 这是 Hibernate 3.x 文档中的引用。您认为这仍然适用于不使用 SLF4J 的 Hibernate 4.x 吗? (4认同)