问题
Using Hibernate (4.3.8) with MySQL, I noticed a bunch of SHOW WARNINGS
statements taking considerable bandwidth in the activity log:
I searched around and it's a pretty common issue (for example) that can apparently be resolved by increasing the log level to ERROR (and that solution is confirmed implemented since at least 4.3.6).
The problem is, I don't actually know how to do this. My knowledge of Hibernate is about the bare minimum necessary to work with it. The previously linked post solved it by editing Logback settings in logback.xml
but I'm not using Logback. I'm using all the default settings:
- Apparently it uses JBoss Logging at its core.
- I don't have any of the other logging dependencies in my classpath (e.g. slf4j.jar) so I'm definitely not using those. The log messages are just being written out to
System.err
.
So I'm not actually sure how to do this. Here is my configuration file:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/xxxxx</property>
<property name="connection.username">xxxxx</property>
<property name="connection.password">xxxxx</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.isolation">2</property>
<property name="connection.pool_size">10</property>
<property name="current_session_context_class">thread</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- <property name="show_sql">true</property> -->
<!-- <property name="hbm2ddl.auto">create</property> -->
<mapping resource="hibernate.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Here are the dependencies in the build path; there's Jettison and Joda, the MySQL driver, and then everything from Hibernate's required
dependency directory and nothing else:
How do I increase the log level or otherwise disable SHOW WARNINGS
in this (default settings) case? This mentions "log categories of interest" but I'm not sure how those relate to the configuration file. This page doesn't have any log related properties documented outside the "Logging" section, which mentions SLF4J, but apparently I'm not using SLF4J (how could I be, since it's not in my classpath).
回答1:
The hibernate framework enables the MySQL's SHOW WARNING by default with every query fired, this doubles the number of queries to MySQL and application can realise performance issues. This additional logging of SHOW WARNING by hibernate can be established at -
org.hibernate.engine.jdbc.spi.SqlExceptionHelper#handleAndClearWarnings()
Solution
Make hibernate choose a proper logger. This can be done by adding :
-Dorg.jboss.logging.provider=slf4j
or -Dorg.jboss.logging.provider=log4j
as a JVM runtime parameter.
For slf4j logger, you will need to configure logback.xml
file. Add this :
<logger name="org.hibernate.type" level="ERROR" />
For log4j logger, you will need to add the following line to log4j.properties
:
log4j.logger.org.hibernate.type=ERROR
回答2:
All right. I got this and learned a lot in the process.
TL;DR:
Under the following assumptions ...
- No logging options are explicitly configured.
- The only log related JARs in the classpath are the jboss logging ones (i.e. no slf4j, log4j, etc.).
... Hibernate will automatically select JDK logging via JBoss Logging, and the java.util.logging facilities may be used to control the log level. Therefore, setting the log level of all JDK logs to SEVERE
, at the root logger level (doesn't matter if you do it before or after Hibernate initializes, see below) successfully stops the SHOW WARNING
commands:
LogManager.getLogManager().getLogger("").setLevel(Level.SEVERE);
However, this is a shotgun approach that sets the log level for all registered Logger
s that have their level set to null
(inherit from parent).
JDK Logging Notes
I came to the above solution by:
- Reading the logging doc a few times until it sunk in, and correlating that info with what was in my class path, evidence indicated JDK logging was in use.
- Looked through the list of logger names from
LogManager#getLoggerNames()
. There were quite a few from Hibernate, this confirmed point 1. - I tried to find the logger responsible for
SHOW WARNINGS
but could not. I do know that it is not "org.hibernate.SQL" (changing that log level has no effect) and it is not "org.hibernate" (that log doesn't actually exist). - I printed out the current log levels for all of them and noticed they were all
null
(inherit from parent). - I printed out the hierarchy and saw the root logger (name "") was the only one with a log level set, so I set that log level. Note that because the Hibernate logs are generally set to "inherit", it doesn't matter if you do this before or after Hibernate is configured: If you do it before you'll get no logging, if you do it after you'll still see it's output during initialization and probably get a couple of
SHOW WARNING
s issued as well, but this is no big deal.
So that's how I arrived at the above, and this leaves the following sloppiness in my solution still:
- Shotgun approach, not sure exactly what logger is responsible so they're all disabled.
- Confused by lack of "org.hibernate".
- This only works if JDK logging is in use, which relies on the above assumptions. Putting another supported logging framework in your classpath may lead Hibernate to select a different framework thus rendering the solution ineffective.
- I only tried
SEVERE
, and verified that it was working. Different log levels may also work, but I did not test.
Other Notes
I tried to explicitly find out which logger Hibernate had auto-selected but was unable to determine how to do that (anybody know?). My only wild guess was something in the ServiceRegistry
but there does not appear to be a logging related Service, or at least I couldn't find one.
In general, it's much more predictable to explicitly configure a logging facility and then configure it according to its documentation, as the solution above, for example, breaks merely by adding another JAR to the class path. However, for quick / one-off / inconsequential projects where you're just minimizing configuration files and such, this appears to be the simplest way to cut out the SHOW WARNING
commands.
来源:https://stackoverflow.com/questions/44211525/how-do-i-disable-show-warnings-from-hibernate