Red Hat

In Relation To

The Hibernate team blog on everything data.

Meet Michael Simons

Posted by    |       |    Tagged as Discussions Hibernate ORM Hibernate Search

In this post, I’d like you to meet Michael Simons, a long-time Sping and Hibernate user, and NetBeans Dream Team member.

Michael Simons, align=
  1. Hi, Michael. Would you like to introduce yourself and tell us a little bit about your developer experience?

    My name is Michael Simons, @rotnroll666 on Twitter.

    I am a 37 year old developer living in Aachen, Germany. As such, I qualify at least age wise as a senior developer. I’ve been in the software industry for nearly 15 years now. I do have a technical apprenticeship and half finished degree in applied Mathematics. I never finished those studies as I landed in the company I still work with, ENERKO INFORMATIK.

    Apart from being a husband and a father of two, I run our local JUG, the Euregio JUG.

    I’m also a member of the NetBeans Dream Team.

    We, at ENERKO INFORMATIK, create software in the energy and utility markets and work both in the technical and geographical parts as well as sales.

    I did really database-centric software for at least 4 years and, I am still fluent in SQL and also PL/SQL. We once did XML processing inside Oracle databases, which works surprisingly well. After the slow death of Oracle Forms Client / Server, we migrated our desktop applications from 2004 onwards to Java Swing.

    Around that time I played around with Hibernate for the first time. It seemed like the golden bullet back then to get table rows into objects. It wasn’t. But that I learned much later. As Gavin King said: „Just because you’re using Hibernate, doesn’t mean you have to use it for everything.“

    Apart from „boring“ business application, I’ve been not only blogging for a long time but ran several online communities, one of them still alive. Daily Fratze is a daily photo project started in 2005 as a PHP application. Then, in 2006 became a Ruby on Rails site and by 2010, I started migrating it to a Spring and Hibernate backend.

    Looking back at that code I notice how much I didn’t know about the purpose and intention of JPA / Hibernate. As it is true for a lot of stuff, you have to know your tools and the stuff they are designed for. Not all relations are meant to be materialized in objects, not all queries can be generated. And knowledge about when a Session is flushed and when not is essential. It’s not enough to know SQL to fully utilize Hibernate, but it’s also not enough to know Hibernate for abstracting persistence away. I changed the flaws in the site code, but you as the reader of this interview must not learn it the hard way, I really recommend Vlad Mihalcea's book High-Performance Java Persistence.

    My biking project and the site and API of the Euregio JUG are my latest public projects that represent the stuff learned with the experience above. I use those projects as reference projects for my work.

    Since several years, I mostly use NetBeans exclusively for all kind of software development. It supports me for plain Java, Spring, insanely well for JPA entities (build in checks for queries, coding style), for front-end (HTML as well as JavaScript). Most important, it has great integration for code quality related tools like JaCoCo, Sonar and more.

  2. You’ve designed the Java User Group Euregio Maas-Rhine site. Can you tell us what frameworks have you used?

    For Euregio JUG (source is on GitHub), I chose the following:

    • Spring Boot as the application container and glue for

      • Spring Framework and MVC

      • JPA and its implementation Hibernate

      • Spring Data JPA

    • The frontend is done pretty old school by server side rendered templates using Thymeleaf.

      As a rule of the thumb I’d choose the following stack when using any kind of SQL data store:

    • automatic database migrations using Flyway or Liquibase

    • JPA / Hibernate together with Spring Data JPA as long as I can express my domain model as entities and tables

    • JPQL queries if necessary with the benefit that they are checked at application start

    • No native queries hidden away in some annotations

    • If I have to do native queries, I’ll choose Springs JDBC template or since 2015 jOOQ if applicable.

    • My rule for switching to native queries is when I do have projections or „hard“ analytics that would take an awful lot of Java Code instead of a few lines SQL.

  3. Why did you choose Hibernate ORM and Search over other frameworks and did it match your expectations?

    From my background, the data model has always been essential. I worked with awesome models and not so great ones. If you can map your domain to a data model, having a working domain driven design, Hibernate helps you a lot to materialize it back into Java.

    We want to publish articles (posts) and events on the site. People should be able to register for those events, one time each. This fits perfectly into a simple and well understandable domain model that maps perfectly to objects and entities.

    Why bother writing those plain SQL statements for selecting and updating stuff myself?

    I chose the combination of Hibernate and Spring Data JPA for a reason: The domain I map in Hibernate facilitates all the „magic“ Spring Data JPA does: Generating queries, conditions and such: I hardly have to write anything myself.

    If you chose JPA / Hibernate ORM in your project, I really recommend adding Spring Data JPA to the mix. Even if it’s a Java EE project. Spring Data JPA is a bit harder to configure there but provides the user with a lot of helpful stuff.

    Using Hibernate Search integration was an experiment. I’m using it for a long time now on my daily photo project. With little effort, my entities provide access to a Lucene based index and I don’t have to fight with SOLR.

    The EuregJUG site has no local storage in contrast to my daily photo project. So, I had to test drive the upcoming Elastic Search integration in 5.6.0, which works with the same set of annotations, the same entities but not against a local index but against a remote Elastic search index. You can see it in those commits described here and use it here.

    It really isn’t much stuff added, it fits into the repository / DDD approach and matches my expectations.

    Regarding Spring Boot, I’ve been doing Spring now for more than 7 years and Boot since early 2014. It has an awesome community and actually never disappointed me.

  4. We always value feedback from our users, so can you tell us what you’d like us to improve or are there features that we should add support for?

    As a Hibernate user the most common problems I had during the time which I didn’t know exactly what I was doing: Having problems mapping my tables, slow queries and such. Also throwing Hibernate at problems that would have been a better fit for plain SQL caused problems. In both cases, those problems could be solved on my end.

    The experience in Hibernates bug tracker is improving a lot lately and I would appreciate an even better integration with Spring Data JPA.

    To close this, I have to say that I really like the stack mentioned above. We have reached a quality of component where you can really work well from a Domain Driven Design perspective, switch to SQL if needed and still having a clean architecture with clean, testable code. Problems that have been around 10 years ago most often gone.

    It’s really not hard to get an application up and running, including unit and integration tests. If you leave aside the hypes, you can concentrate on both actual problems and on enabling people to learn and do their jobs.

    I really like the fact that Hibernate Spatial find its way into ORM itself. If you have correctly mapped entities and you need to query them via spatial regions, that stuff is really helpful and works quite well. I’d appreciate more information there.

Thank you, Michael, for taking your time. It is a great honor to have you here. To reach Michael, you can follow him on Twitter.

Meet Petar Tahchiev

Posted by    |       |    Tagged as Discussions Hibernate ORM

In this post, I’d like you to meet Petar Tahchiev, a long-time Hibernate user, and open-source contributor.

I had the chance of meeting Petar in Cluj-Napoca. Here you can see Petar opening a Hibernate Pull Request that he recently sent us for review.

Petar Tahchiev, align=
  1. Hi, Petar. Would you like to introduce yourself and tell us a little bit about your developer experience?

    Hi Vlad, thanks for having me. My name is Petar Tahchiev, and I am a Java developer from Bulgaria. My experience with open-source dates back to 2006 when I joined the Apache Software Foundation as Jakarta Cactus lead developer. I also became an Apache Maven committer later that year, and I also co-authored the second edition of JUnit in Action.

    While I kept the open-source as a hobby, on a professional level I spent the last eight years of my life implementing e-commerce projects for some of the largest corporations in the world using proprietary software. Then, I finally decided that I can build a way better e-commerce platform using the latest and greatest of the open-source software and thus combine my hobby with my job. And this is actually how Nemesis Software was born.

  2. You are developing the Nemesis platform. Can you tell us what’s the main goal of such a platform?

    Sure thing.

    Well, Nemesis is an e-commerce platform, although e-commerce is just one of many other modules. It’s basically a Spring Boot application with a modular architecture where customers can select the different modules they want to use so they can specify what kind of project they are going to build. Each module has a Spring Boot auto-configuration and consists of a set of JPA entities, a set of services that operate with those entities and different configuration properties to allow you to customize the given module.

    The modules of the nemesis platform allow you to customize completely the purpose of the platform. We have modules for e-commerce, B2B commerce, CMS, analytics, financial services, you name it. This way you can pick the right modules for you and initialize the database with the right columns/tables, etc.

    For initializing the database, we use Hibernate’s hbm2ddl schema export tool which produces SQL scripts and then we also use FlywayDB to execute the SQL scripts and version the database.

    Our platform also comes with a Maven archetype so our customers can generate a project and have it up-and-running in less than 5 minutes, and on top of all that the generated project is designed to be a 12-factor app so you can easily deploy it to any cloud provider out there.

  3. Nemesis is using Hibernate for data persistence. Why did you choose Hibernate and did it match your expectations?

    Yes indeed, although most of our clients are huge corporations and sometimes they are biased on the products they want to use So, we want it to be easy for us to switch the JPA provider if such a need ever occurs. That is the reason why we want to stay as close as possible to any JSR standard.

    Nevertheless, out-of-the-box our platform comes with Hibernate as a JPA provider, and this is what we recommend to our clients. The reasons behind this are several. While we have researched most of the JPA providers, we consider Hibernate to be the most mature project with the largest community out there. That’s something really important for us - we want to provide our clients with the fastest time-to-market development, and to be able to do that, we need to use a technology stack that is closest to most of the developers.

    It turned out that Hibernate is one of the most popular Java projects among regular developers. Another reason we chose Hibernate is that it has a very carefully planned release schedule so we know exactly when a new feature or a fix will be shipped. So far, it has proven to be an excellent choice.

  4. Your platform competes with SAP. Do you think that using open-source frameworks like Spring and Hibernate is a competitive advantage for you?


    I can spend days if not weeks talking about the importance of using open-source tools like Spring and Hibernate compared to proprietary software like SAP, or IBM.

    On the one hand, you get access to a large pool of resources - developers all over the world they know Spring, Hibernate, Tomcat, Drools, etc. So, it’s a lot easier for them to pick up the software and just be productive.

    Having to choose from a large pool of resources means cheaper implementation costs for our customers compared to niche products.

    When using open-source software our customers also get to use first-class documentation (great work on the Hibernate documentation by the way). And, if by any chance they can’t find anything in the documentation, they can always download the source code and debug to see what’s happening, or even patch it and contribute back to the community.

    And that’s just the tip of the iceberg - the biggest benefit of all is that our clients actually get one more level of support. If our customer’s development team has troubles with the open-source tools, they can always google the error they get, and, only when they don’t find what they are looking for, they come to our customer support.

    This actually saves us a lot of time because we know when someone comes to us, it is most likely because of an issue in our own software.

Thank you, Petar, for taking your time. It is a great honor to have you here. To reach Petar, you can follow him on Twitter.

Hibernate Validator 5.3.0.Final is out

Posted by    |       |    Tagged as Hibernate Validator Releases

There has been a lot of release activity on the Hibernate front lately and it is my pleasure to announce that Hibernate Validator just joined the party with the release of Hibernate Validator 5.3.0.Final.

What’s new since 5.3.0.CR1

5.3.0.CR1 was a candidate release so we did not change much!

Marco Davi reported on Stackoverflow that the property path generated for type arguments constraints could be improved so we fixed it. You should now be able to exploit type arguments constraints violations more easily.

Ahmed Al Hafoudh contributed a translation for Slovak for our default messages.

You can find the complete list of all addressed issues in the change log.

Hey! I missed the previous announcements!

If you missed what we already announced for 5.3.0, the most important changes are:

  • Dynamic payloads for constraints

  • A new programmatic API for constraint definition and declaration

Please consult the announcements for more information:

Getting the release

Hibernate Validator 5.3.0.Final should be a drop-in replacement in most cases. Please consult our migration guide before upgrading your application to 5.3.0.Final.

To get the release with Maven, Gradle etc. use the GAV coordinates org.hibernate:{hibernate-validator|hibernate-validator-cdi|hibernate-validator-annotation-processor}:5.3.0.Final.

Alternatively, a distribution bundle containing all the bits is provided on SourceForge (TAR.GZ, ZIP).

To get in touch, use the following channels:

What’s next?

We are going to prepare a 5.4 release with support for validation contributed by Lukas Niemeier and Willi Schönborn from Zalando and a lot of improvements to the annotation processor thanks to the great work of Marko Bekhta.

We are actively working on Bean Validation 2.0 and Hibernate Validator 6 with a strong focus on supporting Java 8 new features (and much more!). The more the merrier, so feel free to join us: drop ideas, comment on others' proposals, now is the time to define the future of Bean Validation. You can find all the necessary information on the Bean Validation website.

Introducing Hibernate Search Sort DSL

Posted by    |       |    Tagged as Hibernate Search

With Elasticsearch support coming as a technological preview in Hibernate Search 5.6, you would think we’re leaving out other features. Well, think again! Enters the Sort DSL, which will work with Elasticsearch of course, but also with the good ol' Lucene backend.

The point here is to provide an API to build sort descriptions easily, without knowing everything about Hibernate Search features added on top of Lucene, such as DistanceSortField. And while we’re at it, we’re making it a modern, fluid API.

Most common case: sorting by field

The QueryBuilder interface now has an additional sort() method:

QueryBuilder builder = fullTextSession.getSearchFactory()
Query luceneQuery = builder.all().createQuery();
FullTextQuery query = fullTextSession.createFullTextQuery( luceneQuery, Book.class );
Sort sort = builder
    .byField("author").desc() // Descending order
    .andByField("title") // Default order (ascending)
List results = query.list();

Of course, other kinds of sort are available. Let’s have a look!

Sorting by relevance

The relevance sort is also available with byScore(). Obviously, there’s one key difference with that one: the sort is descending by default, so you get the most relevant results (higher scores) first. If you need the least relevant results, fear not, we got you covered with byScore().asc().

Sorting by distance

If your entity has some spatial fields you may also build spatial sorts:


Stabilizing with byIndexOrder()

byIndexOrder offers an arbitrary, yet deterministic sort. This comes handy when you want to stabilize your sort:


That way, if there are two books with the same title in your index, they will always keep the same relative order from one query to another.

Handling missing values

What if you’re sorting books by publishing date, and some of them haven’t even been published yet? No worry, you may decide whether the unpublished books will appear first or last:

    .byField("publishingDate_sort").desc() // Most recently published first
      .onMissingValue().sortFirst() // Not published yet => put this upper on the list
    .andByField("custom_id_sort") // Default for the case when multiple books have no publishing date

Accessing native features

Let’s assume you’re using an external backend, such as Elasticsearch. You may want to take advantage of a brand-new feature that appeared in the last snapshot of this backend, that feature you just spotted this morning and that would really save you of a lot of trouble on your project. But, hey, the Hibernate Search team is not on the same time zone, and even if they’re providing fast support, you’re not getting the feature pushed into Hibernate Search in time to meet your deadline. Which is this evening, by the way.

Well, guess what: you can use that feature anyway. The sorting API also allows using native sorts. When using the Elasticsearch backend, it means passing the JSON description of this sort, which will be added to the Elasticsearch query as is:

    .byNative("", "{'order':'asc', 'mode': 'min'}")


Of course, one could point out that this API is not really backend-independent. The API itself, its interfaces and methods, mostly are, but the returned type (Sort) is clearly bound to Apache Lucene.

Well, one day at a time: the API in its current form can be adapted to be completely backend-agnostic, so it’s paving the way to Hibernate Search 6.x, while still requiring no change to any other contract such as FullTextQuery.setSort(Sort). And that means it’s available directly in 5.6.0.Beta3!

So be sure to check it out, and to check the documentation for more information. Or, you know, since it’s a fluid API, you can simply use your IDE autocomplete feature and see what’s available!

In any case, feel free to contact us for any question, problem or simply to give us your feedback!

Hibernate Community Newsletter 20/2016

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.


Steven Feuerstein, a well-known Oracle PL/SQL author, wrote an article in which he’s Looking for stories about using Hibernate with Oracle Database. Hibernate ORM is very suitable for OLTP, especially for writing to the database. Check out the comment section for more details.

Since Hibernate 5.2, you can now configure the JDBC batch size on a per Session basic. Check out this article for more details about this new feature.

Thorben Janssen wrote an article about JPQL query capabilities and limitations.

If you want to use Java 1.8 Optional with JPA entities, check out this post for how you can do it without affecting other Java EE guarantees.

SitePoint has published a new article about Hibernate schema migrations with FlywayDB. Although Hibernate comes with a schema generation tool, for a production environment, an automatic schema management tool that uses database-specific scripts is a much better choice.

Time to upgrade


The latest version of our main development branch, with experimental Elasticsearch integration.


Essentially the same as 5.6.0.Beta3, but compatible with Hibernate ORM version 5.2.x.


A maintenance release of our stable branch.

The first hibernate OGM 5.1 Alpha and 5.0.2 Final

Posted by    |       |    Tagged as Hibernate OGM Releases

Good news!

We released Hibernate OGM 5.1 Alpha1 and 5.0.2 Final!

What’s new?

Hibernate OGM 5.0.2.Final

Hibernate OGM 5.0.2.Final now supports MongoDB 3.2 and it’s still backward compatible with Hibernate OGM 5.0.1.Final.

If you need to upgrade from a version before 5.0, you can find help on the migration notes.

The 5.0.2.Final changelog contains all the details about the changes in this release.

Hibernate OGM 5.1.0.Alpha1

Hibernate OGM 5.1.0.Alpha1 brings support for Neo4j in remote mode. The user will have the option to choose between the new Bolt protocol or the more familiar HTTP interface.

We also started to re-work the way Hibernate OGM groups operations before running them; this reduce the number of calls and commands to execute on the datastore, leading to better performance.

The 5.1.0.Alpha1 changelog contains all the details about the changes in this release.

How can I try the remote Neo4j dialect?

You can test Hibernate OGM support for Neo4j adding the following dependency to your project:


and setting the following properties:

# Required
hibernate.ogm.datastore.provider = neo4j_bolt # or neo4j_http

# Optional =
hibernate.ogm.datastore.username = example_username
hibernate.ogm.datastore.password = example_password

You can get more information about this integration and how to configure it in the Neo4j section of the documentation.

Where can I get them?


You can get the required core library using the following Maven coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.0.2.Final

and these are the backends currently available:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.0.2.Final

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.0.2.Final

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.0.2.Final

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.0.2.Final

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.0.2.Final

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.0.2.Final

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.0.2.Final

Alternatively, you can download archives containing all the binaries, source code and documentation from Sourceforge.


You can get the required core library using the following Maven coordinates:

  • org.hibernate.ogm:hibernate-ogm-core:5.1.0.Alpha1

and these are the backends currently available for 5.1.0.Alpha1:

  • Cassandra: org.hibernate.ogm:hibernate-ogm-cassandra:5.1.0.Alpha1

  • CouchDB: org.hibernate.ogm:hibernate-ogm-couchdb:5.1.0.Alpha1

  • Infinispan: org.hibernate.ogm:hibernate-ogm-infinispan:5.1.0.Alpha1

  • Ehcache: org.hibernate.ogm:hibernate-ogm-ehcache:5.1.0.Alpha1

  • MongoDB: org.hibernate.ogm:hibernate-ogm-mongodb:5.1.0.Alpha1

  • Neo4j: org.hibernate.ogm:hibernate-ogm-neo4j:5.1.0.Alpha1

  • Redis: org.hibernate.ogm:hibernate-ogm-redis:5.1.0.Alpha1

Alternatively, you can download archives containing all the binaries, source code and documentation from Sourceforge.

What’s next?

The major addition in the next release will be the integration with Infinispan remote via the HotRod protocol.

How can I get in touch?

You can find us through the following channels:

We are looking forward to hear your feedback!

Today we have three releases of Hibernate Search!

I’m proud to announce our team is a bit larger nowadays, and more contributors are volunteering too, so we managed to increase the development pace. Today we release version 5.6.0.Beta3, 5.7.0.Alpha1 and 5.5.5.Final.

Version 5.6.0.Beta3

the latest version of our main development branch, with experimental Elasticsearch integration.

Version 5.7.0.Alpha1

essentially the same as 5.6.0.Beta3, but compatible with Hibernate ORM version 5.2.x.

Version 5.5.5.Final

a maintenance release of our stable branch.

A 5.7 preview released when 5.6 isn’t out yet?

Let me explain this unusual decision was taken to accomodate for the needs of you all.

The 5.6 series is creating a lot of anticipation with the Elasticsearch integration being a very welcome new feature; it’s meant to be an experimental new feature as we won’t break our APIs yet while all integration needs are analyzed, still it’s taking a bit longer than expected and even though it’s and experimental feature we don’t want to rush it and need to finish it up properly.

In the meantime the Hibernate ORM project released a series 5.2.x, and several users have been asking to get an Hibernate Search version compatible with it. We could not upgrade our 5.6 series yet, as then people using an older Hibernate ORM would not be able to play with the Elasticsearch integration.

So now that 5.6 is in good shape - we decided the next release will be a candidate release - we felt we could already publish a 5.7 version, which is just exactly the same but in a new branch made compatible with the very latest Hibernate ORM.

How is the Elasticsearch integration coming?

It’s maturing at high speed. The biggest obstacles have been resolved, so we definitely look out for more feedback at this point; as mentioned, the next version will be a candidate release.

Hibernate Search now has a proper Sorting API: watch this space as we’ll publish a dedicated blog about it, or get a peek at the query sorting paragraph in the documentation.

This is an important milestone, as it makes sorting queries on Elasticsearch possible through our DSL.

How to get these releases

All versions are available on Hibernate Search’s web site.

Ideally use a tool to fetch it from Maven central; these are the coordinates:


Downloads from Sourceforge are available as well.

Third bug-fix release for ORM 5.2

Posted by    |       |    Tagged as Hibernate ORM Releases

The Third bug-fix release for Hibernate ORM 5.2 has just been published. It is tagged at

The complete list of changes can be found here (or here for people without a Hibernate Jira account).

For information on consuming the release via your favorite dependency-management-capable build tool, see

The release bundles can be obtained from SourceForge or BinTray.

Hibernate Performance Tuning and Best Practices

Posted by    |       |    Tagged as Discussions Hibernate ORM

This article is based on the latest chapter that’s been added to the Hibernate User Guide. The Performance Tuning and Best Practices chapter aims to help the application developer to get the most out of their Hibernate persistence layer.

Every enterprise system is unique. However, having a very efficient data access layer is a common requirement for many enterprise applications. Hibernate comes with a great variety of features that can help you tune the data access layer.

Schema management

Although Hibernate provides the update option for the configuration property, this feature is not suitable for a production environment.

An automated schema migration tool (e.g. Flyway, Liquibase) allows you to use any database-specific DDL feature (e.g. Rules, Triggers, Partitioned Tables). Every migration should have an associated script, which is stored on the Version Control System, along with the application source code.

When the application is deployed on a production-like QA environment, and the deploy worked as expected, then pushing the deploy to a production environment should be straightforward since the latest schema migration was already tested.

You should always use an automatic schema migration tool and have all the migration scripts stored in the Version Control System.


Whenever you’re using a framework that generates SQL statements on your behalf, you have to ensure that the generated statements are the ones that you intended in the first place.

There are several alternatives to logging statements. You can log statements by configuring the underlying logging framework. For Log4j, you can use the following appenders:

### log just the SQL

### log JDBC bind parameters ###

However, there are some other alternatives like using datasource-proxy or p6spy. The advantage of using a JDBC Driver or DataSource Proxy is that you can go beyond simple SQL logging:

Another advantage of using a DataSource proxy is that you can assert the number of executed statements at test time. This way, you can have the integration tests fail when a N+1 query issue is automatically detected.

While simple statement logging is fine, using datasource-proxy or p6spy is even better.

JDBC batching

JDBC allows us to batch multiple SQL statements and to send them to the database server into a single request. This saves database roundtrips, and so it reduces response time significantly.

Not only INSERT and UPDATE statements, but even DELETE statements can be batched as well. For INSERT and UPDATE statements, make sure that you have all the right configuration properties in place, like ordering inserts and updates and activating batching for versioned data. Check out this article for more details on this topic.

For DELETE statements, there is no option to order parent and child statements, so cascading can interfere with the JDBC batching process.

Unlike any other framework which doesn’t automate SQL statement generation, Hibernate makes it very easy to activate JDBC-level batching as indicated in the Batching chapter, in our User Guide.


Choosing the right mappings is very important for a high-performance data access layer. From the identifier generators to associations, there are many options to choose from, yet not all choices are equal from a performance perspective.


When it comes to identifiers, you can either choose a natural id or a synthetic key.

For natural identifiers, the assigned identifier generator is the right choice.

For synthetic keys, the application developer can either choose a randomly generates fixed-size sequence (e.g. UUID) or a natural identifier. Natural identifiers are very practical, being more compact than their UUID counterparts, so there are multiple generators to choose from:




Although the TABLE generator addresses the portability concern, in reality, it performs poorly because it requires emulating a database sequence using a separate transaction and row-level locks. For this reason, the choice is usually between IDENTITY and SEQUENCE.

If the underlying database supports sequences, you should always use them for your Hibernate entity identifiers.

Only if the relational database does not support sequences (e.g. MySQL 5.7), you should use the IDENTITY generators. However, you should keep in mind that the IDENTITY generators disables JDBC batching for INSERT statements.

If you’re using the SEQUENCE generator, then you should be using the enhanced identifier generators that were enabled by default in Hibernate 5. The pooled and the pooled-lo optimizers are very useful to reduce the number of database roundtrips when writing multiple entities per database transaction.


JPA offers four entity association types:

  • @ManyToOne

  • @OneToOne

  • @OneToMany

  • @ManyToMany

And an @ElementCollection for collections of embeddables.

Because object associations can be bidirectional, there are many possible combinations of associations. However, not every possible association type is efficient from a database perspective.

The closer the association mapping is to the underlying database relationship, the better it will perform.

On the other hand, the more exotic the association mapping, the better the chance of being inefficient.

Therefore, the @ManyToOne and the @OneToOne child-side association are best to represent a FOREIGN KEY relationship.

The parent-side @OneToOne association requires bytecode enhancement so that the association can be loaded lazily. Otherwise, the parent-side is always fetched even if the association is marked with FetchType.LAZY.

For this reason, it’s best to map @OneToOne association using @MapsId so that the PRIMARY KEY is shared between the child and the parent entities. When using @MapsId, the parent-side becomes redundant since the child-entity can be easily fetched using the parent entity identifier.

For collections, the association can be either:

  • unidirectional

  • bidirectional

For unidirectional collections, Sets are the best choice because they generate the most efficient SQL statements. Unidirectional Lists are less efficient than a @ManyToOne association.

Bidirectional associations are usually a better choice because the @ManyToOne side controls the association.

Embeddable collections (`@ElementCollection) are unidirectional associations, hence Sets are the most efficient, followed by ordered Lists, whereas bags (unordered Lists) are the least efficient.

The @ManyToMany annotation is rarely a good choice because it treats both sides as unidirectional associations.

For this reason, it’s much better to map the link table as depicted in the Bidirectional many-to-many with link entity lifecycle User Guide section. Each FOREIGN KEY column will be mapped as a @ManyToOne association. On each parent-side, a bidirectional @OneToMany association is going to map to the aforementioned @ManyToOne relationship in the link entity.

Just because you have support for collections, it does not mean that you have to turn any one-to-many database relationship into a collection.

Sometimes, a @ManyToOne association is sufficient, and the collection can be simply replaced by an entity query which is easier to paginate or filter.


JPA offers SINGLE_TABLE, JOINED, and TABLE_PER_CLASS to deal with inheritance mapping, and each of these strategies has advantages and disadvantages.

  • SINGLE_TABLE performs the best in terms of executed SQL statements. However, you cannot use NOT NULL constraints on the column-level. You can still use triggers and rules to enforce such constraints, but it’s not as straightforward.

  • JOINED addresses the data integrity concerns because every subclass is associated with a different table. Polymorphic queries or `@OneToMany base class associations don’t perform very well with this strategy. However, polymorphic @ManyToOne` associations are fine, and they can provide a lot of value.

  • TABLE_PER_CLASS should be avoided since it does not render efficient SQL statements.


Fetching too much data is the number one performance issue for the vast majority of JPA applications.

Hibernate supports both entity queries (JPQL/HQL and Criteria API) and native SQL statements. Entity queries are useful only if you need to modify the fetched entities, therefore benefiting from the automatic dirty checking mechanism.

For read-only transactions, you should fetch DTO projections because they allow you to select just as many columns as you need to fulfill a certain business use case. This has many benefits like reducing the load on the currently running Persistence Context because DTO projections don’t need to be managed.

Fetching associations

Related to associations, there are two major fetch strategies:


  • LAZY

Prior to JPA, Hibernate used to have all associations as LAZY by default. However, when JPA 1.0 specification emerged, it was thought that not all providers would use Proxies. Hence, the @ManyToOne and the @OneToOne associations are now EAGER by default.

The EAGER fetching strategy cannot be overwritten on a per query basis, so the association is always going to be retrieved even if you don’t need it. More, if you forget to JOIN FETCH an EAGER association in a JPQL query, Hibernate will initialize it with a secondary statement, which in turn can lead to N+1 query issues.

So, EAGER fetching is to be avoided. For this reason, it’s better if all associations are marked as LAZY by default.

However, LAZY associations must be initialized prior to being accessed. Otherwise, a LazyInitializationException is thrown. There are good and bad ways to treat the LazyInitializationException.

The best way to deal with LazyInitializationException is to fetch all the required associations prior to closing the Persistence Context. The JOIN FETCH directive is goof for @ManyToOne and OneToOne associations, and for at most one collection (e.g. @OneToMany or @ManyToMany). If you need to fetch multiple collections, to avoid a Cartesian Product, you should use secondary queries which are triggered either by navigating the LAZY association or by calling Hibernate#initialize(proxy) method.


Hibernate has two caching layers:

The first-level cache is not a caching solution "per se", being more useful for ensuring REPEATABLE READ(s) even when using the READ COMMITTED isolation level.

While the first-level cache is short lived, being cleared when the underlying EntityManager is closed, the second-level cache is tied to an EntityManagerFactory. Some second-level caching providers offer support for clusters. Therefore, a node needs only to store a subset of the whole cached data.

Although the second-level cache can reduce transaction response time since entities are retrieved from the cache rather than from the database, there are other options to achieve the same goal, and you should consider these alternatives prior to jumping to a second-level cache layer:

  • tuning the underlying database cache so that the working set fits into memory, therefore reducing Disk I/O traffic.

  • optimizing database statements through JDBC batching, statement caching, indexing can reduce the average response time, therefore increasing throughput as well.

  • database replication is also a very valuable option to increase read-only transaction throughput

After properly tuning the database, to further reduce the average response time and increase the system throughput, application-level caching becomes inevitable.

Topically, a key-value application-level cache like Memcached or Redis is a common choice to store data aggregates. If you can duplicate all data in the key-value store, you have the option of taking down the database system for maintenance without completely loosing availability since read-only traffic can still be served from the cache.

One of the main challenges of using an application-level cache is ensuring data consistency across entity aggregates. That’s where the second-level cache comes to the rescue. Being tightly integrated with Hibernate, the second-level cache can provide better data consistency since entries are cached in a normalized fashion, just like in a relational database. Changing a parent entity only requires a single entry cache update, as opposed to cache entry invalidation cascading in key-value stores.

The second-level cache provides four cache concurrency strategies:

READ_WRITE is a very good default concurrency strategy since it provides strong consistency guarantees without compromising throughput. The TRANSACTIONAL concurrency strategy uses JTA. Hence, it’s more suitable when entities are frequently modified.

Both READ_WRITE and TRANSACTIONAL use write-through caching, while NONSTRICT_READ_WRITE is a read-through caching strategy. For this reason, NONSTRICT_READ_WRITE is not very suitable if entities are changed frequently.

When using clustering, the second-level cache entries are spread across multiple nodes. When using Infinispan distributed cache, only READ_WRITE and NONSTRICT_READ_WRITE are available for read-write caches. Bear in mind that NONSTRICT_READ_WRITE offers a weaker consistency guarantee since stale updates are possible.

For more about Hibernate Performance Tuning, check out the High-Performance Hibernate presentation from Devoxx France.

Hibernate Community Newsletter 19/2016

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.


Michael Simons wrote a very good article about using Hibernate Search with Elasticsearch on Pivotal Cloud Foundry.

On our blog, I wrote an article about configuring Hibernate to use a custom timezone (e.g. UTC) that’s different than the default JVM one.

For our Russian-speaking readers, Николай Алименков has written a very good post about Hibernate usage scenarios. Nikolai is one of the organizers of JEEConf, and together with Igor Dmitriev, they gave several presentations about Hibernate performance tuning.

If you want to learn what is the best way to handle the infamous LazyInitializationException, check out this article.

Alejandro Gervasio wrote a very good article, Persisting Java Objects the Easy Way on SitePoint.

Hibernate offers a very various ways to load entity attributes lazily. Check out this article for more details.

Thomas Kratz has written a very article about using Hibernate JSON types with Kotlin.

When developing Hibernate, we are using the hibernate-testing module to simplify Session/Transaction management, as described in this article. The hibernate-testing library is available on Maven Central, so it’s very easy to make use of it in your project. Happy testing!


Patrycja Wegrzynowicz gave a very interesting presentation at Java One about Second-level Caching. The presentation goes from defining what response time is and how you can level it up using caching. At the end of the presentation, Patrycja discusses how Ehacache and Infinispan implement the Hibernate second-level caching contract.

back to top