Hibernate Caveats

If you are using Java and you have to save or load data from a database, you will likely use Hibernate since it makes mapping data so much easier. With Hibernate you can model your database structure in code including links between tables. While the usage of Hibernate makes handling database data a lot easier, there are some caveats that you should be aware of.
I once was working on a project where they did a lot of interesting things (not to say weird), such as implementing their own dependency injection system based on some other framework. It is in this project that I encountered my first problem with Hibernate, where after updating an entry the value that you would fetch afterwards was not the updated one, but still the original value. This confused me a lot since the value in the database was updated. The source of the issue is that Hibernate maintains a cache and doing weird things with hibernate connections and sessions could lead to different threads having different hibernate instances and caches which are not updated when needed. This isn't a problem with Hibernate, and in normal cases you shouldn't face this issue, but it is something you should be aware of.
On another project I had to dig into Hibernate a bit more than I actually liked due to some mapping issue. Hibernate was not loading in all data from my entity causing all kinds of issues in the application. This issue was caused by some bad naming and mapping in the application. This caused Hibernate to not lazily load the data because it thought it already did. From Hibernate's point of view, that would make since since a mapping with that name was already loaded. Again this is not really a problem of Hibernate, but again something you have to be aware of and may be difficult to diagnose.
My main problem with Hibernate though, is that it does a lot of magic under the hood. Especially when you have linked objects, Hibernate will load the linked entities (either eagerly or lazily). This means that you could be doing a lot more database queries than you expect. Having a large linked model, you could end up with fetching a lot more data than you need, since Hibernate will load the entity you requested, the linked entities, the entities linked to those entities, etc...
Lazy loading will fix this and prevent Hibernate from loading all that data initially, and delay fetching that data until you need it. This is an improvement, but something you have to be fully aware of. My main problem however is that this is not visible in the code. You don't know whether some data is already loaded or not, will it perform another query or not? You may think that a get on the entity is cheap, but it actually requires another query to actually fetch that data.
Lazy loading comes with it's own caveats as well, if you want to fetch data when you already terminated the hibernate/database session, this will fail. This means that you typically have to keep the session alive for the entire request, which again is something you should try to avoid.
As a result, my current approach is to model Hibernate objects exactly as they are stored in my database. By that I mean that if my database has a column that is a id of some other table (foreign key), I will represent this in my Hibernate object as the id instead of the actual object. This means that my Hibernate model has no links at all! Instead I will always fetch data explicitly myself, which makes queries very explicit. On top of that, instead of only relying on the Hibernate models and doing processing in Java, I prefer to use views that give me exactly the data that I need, this again will allow me to minimise the amount of queries I have to execute.
Subscribe to my newsletter
Read articles from Chris Vesters directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
