Как настроить ведение журнала в Hibernate 4 для использования SLF4J

Hibernate 3.x используется для регистрации. Hibernate 4.x использует . Я пишу автономное приложение, которое использует Hibernate 4 и SLF4J для ведения журнала.

Как настроить Hibernate для входа в SLF4J?

Если это невозможно, как я могу настроить ведение журнала Hibernate вообще?

Справочник Hibernate 4.1 при регистрации начинается с предупреждения о том, что он...

Полностью устаревший. Hibernate использует JBoss Logging, начиная с 4.0. Это будет задокументировано, поскольку мы переносим этот контент в Руководство разработчика.

... продолжает говорить о SLF4J, и поэтому бесполезно. Ни руководство , ни руководство разработчика говорят о регистрации вообще. Также не выполняется руководство по миграции.

Я искал документацию по самому jboss-logging, но я вообще не смог ее найти. страница GitHub неактивна, а JBoss страница проектов сообщества даже не перечислить jboss-logging. Я задавался вопросом, может ли в проекте отслеживать ошибки какие-либо проблемы, связанные с предоставлением документации, но это не так.

Хорошей новостью является то, что при использовании Hibernate 4 внутри сервера приложений, такого как JBoss AS7, регистрация в основном позаботится о вас. Но как я могу настроить его в отдельном приложении?

Ответ 1

Посмотрите 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 являются: jboss, jdk, log4j, slf4j.

Если вы не установите org.jboss.logging.provider, он попытается выполнить jboss, затем log4j, затем slf4j (только если используется журнал) и отмените переход к jdk.

Я использую slf4j с logback-classic:

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.13</version>
        <scope>${logging.scope}</scope>
    </dependency>

и все отлично работают!

ОБНОВЛЕНИЕ Некоторые пользователи используют в основном App.java:

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

но для решений на основе контейнеров это не сработало.

ОБНОВЛЕНИЕ 2 Те, кто считают, что они управляют Log4j с SLF4J для jboss-logging, это не совсем так. jboss-logging напрямую использует Log4j без SLF4J!

Ответ 2

Чтобы заставить SLF4J работать с ведением журнала JBoss без ведения журнала, так как бэкэнд требует использования системного свойства org.jboss.logging.provider=slf4j. Тактика log4j-over-slf4j, похоже, не работает в этом случае, потому что ведение журнала вернется к JDK, если ни Logback, ни log4j на самом деле не присутствуют в пути к классам.

Это немного неприятно, и для того, чтобы получить автоматическое определение для работы, вы видите, что classloader содержит не менее ch.qos.logback.classic.Logger от logback-classic или org.apache.log4j.Hierarchy от log4j, чтобы обмануть JBoss Logging, не отступая от JDK.

Магия интерпретируется в org.jboss.logging.LoggerProviders

UPDATE: добавлена ​​поддержка загрузчика услуг, поэтому можно избежать проблем с автоопределением, объявив META-INF/services/org.jboss.logging.LoggerProviderorg.jboss.logging.Slf4jLoggerProvider в качестве значения). Кажется, добавлена ​​поддержка log4j2.

Ответ 3

Вдохновленный Leif Hypoport post, вот как я "согнулся" Hibernate 4 обратно в slf4j:

Предположим, вы используете Maven.

  • Добавьте org.slf4j:log4j-over-slf4j в качестве зависимости от вашего pom.xml
  • Используя команду mvn dependency:tree, убедитесь, что none из артефактов, которые вы используете, зависит от 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 logs теперь будет проходить через 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.xml при запуске JVM для правильного ведения журнала, например, Jetty Maven Plugin. В этом случае добавьте в свою систему Java logback.configurationFile=./path/to/logback.xml (например, mvn -Dlogback.configurationFile=./target/classes/logback.xml jetty:run).

В случае, если вы все еще получаете "сырой" вывод на консоль stdout Hibernate (например, Hibernate: select ...), тогда вопрос "Переполнение стека" Отключить ведение журнала спящего режима до консоли" может применяются.

Ответ 4

Сначала вы понимаете, что SLF4J не является библиотекой протоколов, ее обходной оберткой. Он сам ничего не регистрирует, он просто делегирует "бэкэндам".

Чтобы настроить "jboss-logging", вы просто добавляете любую структуру журнала, которую хотите использовать в своем пути к классу (наряду с протоколом jboss-logging), а остальные записи jboss-logging.

Я создал справочник, ориентированный на гибернат, в конфигурацию журнала JBoss: http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

Ответ 5

Я использую Hibernate Core 4.1.7.Final plus Spring 3.1.2.RELEASE в автономном приложении. Я добавил Log4j 1.2.17 в мои зависимости, и, похоже, JBoss Logging ведет журнал непосредственно в 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>

Ответ 6

Hibernate 4.3 имеет некоторую документацию о том, как управлять org.jboss.logging:

  • Он ищет путь к классу для поставщика протоколирования. Он ищет slf4j после поиска log4j. Итак, теоретически, гарантируя, что ваш classpath (WAR) не включает log4j и включает в себя API-интерфейс slf4j, а back-end должен работать.

  • В качестве последнего средства вы можете установить системное свойство 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.

Ответ 7

Я использую 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. Он работает как прелесть...

Ответ 8

так что просто он работал в моем проекте. hibernate 4, slf4j, logback. мой проект gradle, но должен быть таким же для maven.

В принципе Абдулл прав. Где он НЕ прав, это то, что вы НЕ ДОЛЖНЫ удалить slf4j из зависимостей.

  • включить для компиляции области:

    org.slf4j: SLF4J-апи

    org.slf4j: log4j-над-SLF4J

    например. для журнала (ch.qos.logback: logback-classic, ch.qos.logback: logback-core: 1.0.12)

  • полностью исключить log4j libs из зависимостей

Результат: спящий журнал с помощью slf4j в logback. конечно, вы должны иметь возможность использовать другую реализацию журнала, чем logback

чтобы убедиться, что log4j не присутствует, проверьте свои библиотеки на пути к классам или web-inf/lib для файлов войны.

конечно, вы установили регистраторы в logback.xml, например.

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

Ответ 9

У меня возникла проблема с записью 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>

Ответ 10

Для всех, кто мог столкнуться с той же проблемой, что и я. Если вы попробовали все другие решения, описанные здесь, и до сих пор не видите запись в режиме спящего режима, работающую с вашим slf4j, это может быть связано с тем, что вы используете контейнер, который имеет в своей папке библиотеки jboss-logging.jar. Это означает, что он предварительно загружается, прежде чем вы сможете даже настроить любую конфигурацию, чтобы влиять на него. Чтобы избежать этой проблемы в weblogic, вы можете указать в файле weblogic-application.xml ухо /META -INF, чтобы предпочесть библиотеку, загруженную из приложения. должен быть аналогичный механизм для других серверных контейнеров. В моем случае я должен был добавить:

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

Ответ 11

Вы пробовали это:

- slf4j-log4j12.jar в случае Log4J. Более подробную информацию см. В документации SLF4J. Для использования Log4j вам также необходимо поместить файл log4j.properties в свой путь к классам. Пример файла свойств распространяется с помощью Hibernate в каталоге src/

просто добавьте эти банки и свойства или log4j xml в путь к классам