• Skip to primary navigation
  • Skip to content
  • Skip to primary sidebar

Thoughts on Java

  • Tutorials ▼
    • Hibernate & JPA Tutorials
    • Hibernate Tips
    • Tutorials on YouTube
  • Books & Courses ▼
    • Hibernate Tips Book
    • Online Training
    • Open Workshops
    • On-Site Training
  • Consulting ▼
    • Consulting Call
    • Project Coaching
  • About ▼
    • About Thoughts on Java
    • Support Thoughts on Java
    • Resources
  • Member Library
You are here: Home / Featured / Hibernate Logging Guide – Use the right config for development and production
Do you live in Europe?
Then I hope to see you at one of my in-person workshops in December 2019. You will learn to use Hibernate advanced features and to improve the performance of your persistence layer.
Join before August 23rd to get the best price!

Hibernate Logging Guide – Use the right config for development and production

By Thorben Janssen 5 Comments

  • tweet 
  • share 
  • share 
  • share 
  • share 
  • email 

Hibernate Logging Guide
Choosing the right logging configuration can make the difference between finding a performance issue during development or suffering from it on production. But it can also create an overhead that slows down your application. You need to decide which information you need and configure your system accordingly.

I, therefore, prefer to use two different configurations:

  • A development configuration which logs enough internal information to understand the database interactions, see the number of executed queries and check the SQL statements.
  • A production configuration which avoids any overhead by logging as few messages as possible.

 

Don’t want to read? You can watch it here!

Follow me on YouTube to not miss any new videos.

Supported logging back-ends

Before we have a look at the different logging categories and levels, let’s have a short look at the logging frameworks supported by Hibernate. Since version 4.0, Hibernate uses the JBoss Logging library to write messages to a log file. This library is a logging bridge that integrates different log frameworks. You can decide which of the following frameworks you want to use for your application:

  1. JBoss LogManager
  2. Log4j 2
  3. Log4j 1
  4. Slf4j
  5. JDK logging

You only need to add your preferred framework to the classpath, and the JBoss Logging library will pick it up. If there are multiple frameworks available, the one with the highest priority will be chosen.

I prefer log4j 2 and will use it for the examples in this post. The concepts and log categories are the same for all frameworks, but the format of the configuration file and the names of the log level can differ. I will show a few different configuration files in this article. Please check the documentation of your logging framework, if yours is not included.

 

Log categories

As all applications and frameworks, Hibernate writes log messages in different categories and log levels.
The categories group log messages for specific topics, like executed SQL statements or cache interactions. The following table shows the most important log categories used by Hibernate:

Category Description
org.hibernate This category contains all messages written by Hibernate. You can use this to analyze unspecific issues or to find categories used by Hibernate.

Be careful, setting this category to a fine log level might create a lot of log output.

org.hibernate.SQL All SQL statements executed via JDBC are written to this log category.

You can use it together with org.hibernate.type.descriptor.sql to get more information about the JDBC parameters and results.

org.hibernate.type.descriptor.sql Hibernate writes the values bound to the JDBC parameters and extracted from the JDBC results to this log category.

This category should be used together with org.hibernate.SQL to also log the SQL statements.

org.hibernate.pretty Hibernate logs the state at flush time of max. 20 entities to this log category.
org.hibernate.cache Information about second level cache activities is written to this log category.
org.hibernate.stat Hibernate writes some statistics for each query to this category. The statistics need to be activated separately (see Activate Hibernate Statistics).
org.hibernate.hql.internal.ast.AST This category groups the HQL and SQL ASTs during query parsing.
org.hibernate.tool.hbm2ddl Hibernate writes the DDL SQL queries executed during schema migration to this log category.

The names of the log levels are defined by your logging framework and define the amount and granularity of the log messages. You can assign a log level to each category. If you do not specify a log level for a specific category, it will inherit the level from its parent category.

 

Don’t use show_sql to log SQL queries

How to get Hibernate to log the executed SQL queries is an often asked question, and the most popular answer on the internet seems to be to set the show_sql parameter in the persistence.xml to true. But please, don’t do this!

Hibernate provides two ways to activate the logging of the executed SQL queries and setting the show_sql parameter to true is the worse one. It has two huge disadvantages:

  1. Hibernate writes all executed SQL statements to standard out without using the logging framework. Therefore, it becomes difficult to define the log file which shall contain these specific log messages. Writing to standard out is also most often much slower than using an optimized logging framework.
  2. The persistence.xml is part of a jar file of your application, and you need to open that binary if you want to activate or deactivate the logging of the SQL statements. The configuration of your logging framework is most often an external text file that can be easily changed on any system.

The better way to activate the logging of executed SQL statements is to set the log level of the org.hibernate.SQL category to DEBUG (or the corresponding log level of your log framework). Hibernate will write the SQL statements without any information about the values bound to the JDBC parameters or extracted from the query result. If you also want to get this information, you have to set the log level of org.hibernate.type.descriptor.sql to DEBUG (see the development recommendation for an example).

 

Recommended logging configurations

The requirements for production and development systems are very different. During development, you need to know what Hibernate is doing in the background. But logging this information slows down the application, and it’s not required in production. I, therefore, recommend using two different settings:

 

Development

Hibernate is doing a lot of things for you in the background, and that makes it easy to forget that you are still working with a database. But if you want to make sure that your application will perform as you expected, you need to check the number of executed queries and their SQL statements.

To get this information, you need to set the log level for the org.hibernate.SQL category to DEBUG, and if you also want to log the used bind parameter values, you also need to set the org.hibernate.type.descriptor.sql category to trace.

In addition to that, I prefer to activate Hibernate statistics to get a summary of the most critical metrics at the end of each session.

In the following sections, you can see such a logging configuration for different logging frameworks.

Log4J

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{HH:mm:ss,SSS} %-5p [%c] - %m%n

log4j.rootLogger=info, stdout
# basic log level for all messages
log4j.logger.org.hibernate=info

# SQL statements and parameters
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace

Log4J2

<Configuration monitorInterval="60">
    <Properties>
        <Property name="log-path">PropertiesConfiguration</Property>
    </Properties>
    <Appenders>
        <Console name="Console-Appender" target="SYSTEM_OUT">
            <PatternLayout>
                <pattern>
                    [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
                </pattern>>
            </PatternLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="org.hibernate.SQL" level="debug" additivity="false">
            <AppenderRef ref="Console-Appender"/>
        </Logger>
        <Logger name="org.hibernate.type.descriptor.sql" level="trace" additivity="false">
            <AppenderRef ref="Console-Appender"/>
        </Logger>
        <Root level="info">
            <AppenderRef ref="Console-Appender"/>
        </Root>
    </Loggers>
</Configuration>

JDK logger

handlers=java.util.logging.ConsoleHandler

java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

org.hibernate.level=INFO
org.hibernate.SQL.level=FINER
org.hibernate.type.descriptor.sql.level=FINEST

Logback via Slf4j

<configuration>
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<Pattern>
				%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
			</Pattern>
		</encoder>
	</appender>
	<logger name="org.hibernate.SQL" level="debug" additivity="false">
		<appender-ref ref="STDOUT"/>
	</logger>
	<logger name="org.hibernate.type.descriptor.sql" level="trace" additivity="false">
		<appender-ref ref="STDOUT"/>
	</logger>
	<root level="info">
		<appender-ref ref="STDOUT"/>
	</root>
</configuration>

If you use any of these configurations, Hibernate will write a log file that looks very similar to the following one. It was written by log4j, and it shows the Hibernate messages for a session in which I persisted 2 new Author entities, updated one of them afterward and selected all Authors with a given last name.

13:45:20,863 DEBUG [org.hibernate.SQL] - select nextval ('hibernate_sequence')
13:45:20,907 DEBUG [org.hibernate.SQL] - select nextval ('hibernate_sequence')
13:45:20,939 DEBUG [org.hibernate.SQL] - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
13:45:20,950 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [1] as [VARCHAR] - [Thorben]
13:45:20,951 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [2] as [VARCHAR] - [Janssen]
13:45:20,952 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [3] as [INTEGER] - [0]
13:45:20,953 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [4] as [BIGINT] - [1]
13:45:20,960 DEBUG [org.hibernate.SQL] - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
13:45:20,960 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [1] as [VARCHAR] - [Nicolia]
13:45:20,960 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [2] as [VARCHAR] - [Parlog]
13:45:20,961 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [3] as [INTEGER] - [0]
13:45:20,961 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [4] as [BIGINT] - [2]
13:45:21,488 DEBUG [org.hibernate.SQL] - update Author set firstName=?, lastName=?, version=? where id=? and version=?
13:45:21,494 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [1] as [VARCHAR] - [Nicolai]
13:45:21,503 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [2] as [VARCHAR] - [Parlog]
13:45:21,505 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [3] as [INTEGER] - [1]
13:45:21,509 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [4] as [BIGINT] - [2]
13:45:21,510 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [5] as [INTEGER] - [0]
13:45:21,522 DEBUG [org.hibernate.SQL] - select author0_.id as id1_0_, author0_.firstName as firstNam2_0_, author0_.lastName as lastName3_0_, author0_.version as version4_0_ from Author author0_ where author0_.lastName=?
13:45:21,524 TRACE [org.hibernate.type.descriptor.sql.BasicBinder] - binding parameter [1] as [VARCHAR] - [Janssen]
13:45:21,531 TRACE [org.hibernate.type.descriptor.sql.BasicExtractor] - extracted value ([id1_0_] : [BIGINT]) - [1]
13:45:21,541 INFO  [org.hibernate.engine.internal.StatisticalLoggingSessionEventListener] - Session Metrics {
    71600 nanoseconds spent acquiring 1 JDBC connections;
    42200 nanoseconds spent releasing 1 JDBC connections;
    5946500 nanoseconds spent preparing 6 JDBC statements;
    9801200 nanoseconds spent executing 6 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    55887200 nanoseconds spent executing 2 flushes (flushing a total of 4 entities and 0 collections);
    27027800 nanoseconds spent executing 1 partial-flushes (flushing a total of 2 entities and 2 collections)
}

If you don’t need that many information, I recommend starting with removing the configuration of the org.hibernate.type.descriptor.sql category. This will remove the log messages showing the bind parameter values. As you can see in the log file, these are the majority of the written log messages and there are so many of them that the log gets hard read.

 

Production

As long as you do not need to analyze an issue in production, you should log as less information as possible. This can be done by setting all Hibernate related log categories to ERROR. You should also make sure that the Hibernate statistics component is deactivated.

Log4J

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{HH:mm:ss,SSS} %-5p [%c] - %m%n

log4j.rootLogger=info, stdout
# basic log level for all messages
log4j.logger.org.hibernate=error

Log4J2

<Configuration monitorInterval="60">
    <Properties>
        <Property name="log-path">PropertiesConfiguration</Property>
    </Properties>
    <Appenders>
        <Console name="Console-Appender" target="SYSTEM_OUT">
            <PatternLayout>
                <pattern>
                    [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
                </pattern>>
            </PatternLayout>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="org.hibernate" level="error" additivity="false">
            <AppenderRef ref="Console-Appender"/>
        </Logger>
        <Root level="info">
            <AppenderRef ref="Console-Appender"/>
        </Root>
    </Loggers>
</Configuration>

JDK logger

handlers=java.util.logging.ConsoleHandler

java.util.logging.ConsoleHandler.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

org.hibernate.level=SEVERE

Logback via Slf4j

<configuration>
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<Pattern>
				%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
			</Pattern>
		</encoder>
	</appender>
	<logger name="org.hibernate" level="error" additivity="false">
		<appender-ref ref="STDOUT"/>
	</logger>
	<root level="info">
		<appender-ref ref="STDOUT"/>
	</root>
</configuration>

 

Summary

Hibernate supports several logging providers and you can pick the one you prefer by adding it to the classpath of your application.

The log messages are grouped into different categories, and you can activate or deactivate them by assigning a log level for each category.

Writing log messages and collecting the required information takes some time. You should, therefore, switch off all unnecessary log messages in your production configuration.

The development configuration should activate debug logging for some crucial categories like org.hibernate.SQL and I most often also activate Hibernate statistics to find potential performance issues as soon as possible.

If you like to learn more about finding and solving Hibernate related performance issues, have a look at my Hibernate Performance Tuning Training.

  • tweet 
  • share 
  • share 
  • share 
  • share 
  • email 

Related posts:

  1. Ultimate Guide to JPQL Queries with JPA and Hibernate
  2. Ultimate Guide – Association Mappings with JPA and Hibernate
  3. Getting Started With Hibernate
  4. A Beginner’s Guide to JPA’s persistence.xml
Become a Thoughts on Java Supporter to claim your member perks and to help me write more articles like this.

Filed Under: Featured, Hibernate Beginner Tagged With: Configuration

Improve Your Hibernate Skills At An In-Person Workshop

Join before August 23rd to get the best price!

Implement Your Persistence Layer with Ease

Learn More About Hibernate

Need Some Help with Your Project?

Reader Interactions

Comments

  1. Arun Menon says

    December 10, 2015 at 8:13 am

    Thanks. Read the blog and removed show_sql with the mentioned log levels. Thanks.

    Reply
  2. Mohan says

    February 1, 2016 at 11:30 pm

    Did you read this blog post that they faced with enabling debug log caused performance problem?
    https://plumbr.eu/blog/io/how-we-accidentally-doubled-our-jdbc-traffic-with-hibernate

    What is your thoughts on it?

    Reply
    • Thorben Janssen says

      February 1, 2016 at 11:39 pm

      Hi Mohan,

      yes, I saw that post. I can understand the general idea behind that behaviour but most Hibernate users will not expect it. I think an additional property to activate the extra statements would be a good idea.

      The Hibernate is discussing this issue on their mailing list. Seems like we get a fix for that in the future. Until then you should use the ERROR log level in production to avoid it.

      Regards,
      Thorben

      Reply
  3. THEODOROS CHAIKALIS says

    August 4, 2018 at 3:20 pm

    Thank you. But despite my hard efforts. It’s not working on my Payara 5.

    Made a Relevant sof question

    https://stackoverflow.com/questions/51680051/how-can-we-make-logging-sql-statements-in-hibernate-5-and-payara-5-glassfish-w

    Reply
    • Thorben Janssen says

      August 11, 2018 at 2:56 pm

      Hi,

      Did you try Ondrej’s answer? https://stackoverflow.com/a/51703554

      Regards,
      Thorben

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Join over 10.000 developers
in the
Thoughts on Java Library

Ebooks Sidebar Get free access to ebooks, cheat sheets and training videos.
Join Now!
Don't like ads?
Become a Thoughts on Java Supporter.
Special Launch Price

Let’s Connect


Thorben Janssen
Independent consultant, trainer and author
  • Facebook
  • GitHub
  • Google+
  • LinkedIn
  • Twitter
  • xing
  • YouTube

Speaking at

11th September 2019
Workshop Tage 2019 (Switzerland):
Hibernate + jOOQ + Flyway = Die besten relationalen Persistenzframeworks in einem Stack (1-day Workshop - German)

12th September 2019
Workshop Tage 2019 (Switzerland):
Patterns zur Arbeit mit relationalen Daten in Microservice-Architekturen (1-day Workshop - German)

2nd-3rd December 2019
Düsseldorf (Germany):
Advanced Hibernate Workshop (2-day Workshop - English)

4th-6th December 2019
Düsseldorf (Germany):
Hibernate Performance Tuning Workshop (3-day Workshop - English)

Looking for an on-site training?

Featured Post

14 YouTube Channels You Should Follow in 2019

Getting Started With Hibernate

Entities or DTOs – When should you use which projection?

Ultimate Guide – Association Mappings with JPA and Hibernate

Ultimate Guide to JPQL Queries with JPA and Hibernate

Recent Posts

  • The Builder Pattern – How to use it with Hibernate
  • Hibernate Tip: Create an EntityGraph with multiple SubGraphs
  • Fluent Entities with Hibernate and JPA
  • Hibernate Tip: Join Unassociated Entities in Criteria Query
  • Enum Mappings with Hibernate – The Complete Guide
  • 5 JPA Features That Are Easier To Use with Spring Data JPA
  • Hibernate Tip: Many-to-Many Association with additional Attributes
  • Hibernate Tip: Using LEFT JOIN and FETCH JOIN in a CriteriaQuery
  • Date and Time Mappings with Hibernate and JPA
  • Hibernate Tip: How does Hibernate’s native ID generator work
Don't like ads?
Become a Thoughts on Java Supporter.

Copyright © 2019 Thoughts on Java

  • Impressum
  • Disclaimer
  • Privacy Policy