When not to use Hibernate
I have seen quite many development efforts fumble because of JPA/Hibernate. But then I have also seen many projects where Hibernate has given great benefits even when the harsh reality of production is met. Following are some thoughts on when it is better to avoid Hibernate or any ORM for that matter.
When you don’t like it
Some time ago we had discussion about Hibernate in our company and of course there were some people who said something like: “There is a simple rule of thumb when to use Hibernate — never“.
I totally respect that opinion. I would even make it a more generic rule: “never use the tools you don’t like (if you have a choice of course)”. Btw same goes in the opposite direction as well.
When you are not using Rich Domain Model
Indeed I believe this is the primary benefit that ORM provides. It makes it possible to build complex Domain Models that can be persisted. If you still are planning to use Anemic Domain Model then there are simpler tools that help simplifying database access without all the complexity that comes with a full ORM.
Hibernate has support for this but it is not so easy to optimize for such scenario and not sure how well the idea of building complex Domain Model fits here anyway.
When you don’t keep on eye on the SQL being generated at every step of development
I have been in many projects where initially things went quite smoothly but when we got closer to production we discovered many issues related to performance in case of large datasets. Even though I don’t think it makes sense trying to optimize each line of code you write then I do believe that it makes sense to watch what kind of queries are being executed behind the scenes when you may be doing something simple like repository.findRecipientsByUserId. You don’t necessarily need to optimize each query but you should generally avoid things like N+1 queries. Unless you do it from day one it will soon get quite hard to optimize.
Although, ideally you should be able to design your Domain Model ignoring how it is persisted then in reality it is good to make few compromises here and there. For sure you should have some understanding of the size of dataset when considering which things should be accessible via one-to-many relationships and which ones should work via some Repository API.
Domain Model is best suited for write scenario. In read scenarios it gives very little value put can cause significant challenges to performance.
When you don’t have good knowledge about Hibernate in your team and don’t want to take the effort to understand it’s intricacies
On the first project where I used Hibernate we started having some strange concurrency issues in some update scenarios. Instead of trying to understand why these anomalies were happening we simply applied some more hacks. Of course this did not improve the maintainability or robustness of the app.
We had no idea about any of the best practices of using Hibernate. We were doing things like creating the whole one-to-many collection from scratch every time one additional item was added. Neither did we have any idea about the best practices around using business keys for implementing equals and hashcode for Entities.
When you are not in control of your database design
If you have no flexibility on database side then you have to make it work by using some heavy magic on application side. Quite often this results in very strange mappings and using some more exotic Hibernate features like composite primary keys. I once had a project with a bank where all database schema changes needed for the project were defined long before any development had started. What made things even more interesting was that all modifications to database had to be done via stored procedures as per architectural policy. Needless to say we learned quite a lot about Hibernate on that project :)