Как настроить ведение журнала в Hibernate 4 для использования SLF4J
Hibernate 3.x используется slf4j для регистрации. Hibernate 4.x использует jboss-logging. Я пишу автономное приложение, которое использует 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.LoggerProvider
(с org.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 в путь к классам