Hibernate, just stop it!

In 2001 Hibernate was created to ease development for the hordes of unhappy developers fighting with Java’s poor EJB implementation. EJB was so confusing and over-engineered that Hibernate’s simpler approach seemed like pure heaven in contrast.

Eventually hibernate inspired Java’s JPA and became a certified implementation of JPA.

History lesson is over.

Lets look at the status today. Right now Hibernate is a very popular ORM java library, maybe the most popular of them all. And I can’t understand what is wrong with people.

Hibernate promises to simplify database access, it maps your objects to a database schema and is database agnostic.You connect to any relational database you want, annotate your classes and variables, and Hibernate does all the magic. No SQL! Magic! Magic I tell you!!

I have tried using Hibernate for several projects. Every time, using Hibernate has been ok until at some point I start using many-to-many relationships, or want control over the order of things to be loaded. I start fiddling with the annotations, lazy loading, try HQL, and start getting pissed off. Then I look at what sql queries are being sent to the database, and it hits me every time:

As soon as a project gets to a certain size Hibernate’s magic ends up getting in the way.

I most often know how I want the database to be, and I know SQL enough to get the results I want. If I want to tune queries or write queries, then SQL is the bloody language for it. Not HQL or any other ORM bastardized substitute. What is wrong with using the query language created for this purpose?

Hibernate is useful for newbie developers that are scared of SQL and just want it to go away, while they riddle their class files with annotations, and let Hibernate automatically generate a database and puke endless sql queries over it.

Those developers should grow up and start asking themselves why they are using a library that mangles their understanding of how databases work, messes up the classes with annotations, and has a tendency to need tuning to get the number of queries and performance to an acceptable level once your project goes beyond crazy simple.

Am I missing something here, or is it stupid to have to tune the library that is supposed to simplify your database access, so that it isn’t interfering with your programs access to the underlying database?

I agree that using JDBC directly is a hassle. Having to do all the setup, handle connections, make sure you call rollback when an exception occurs in a transaction, do your own caching and so on… it can get tedious.

A friend and colleague of mine (Lars Aaberg) has the same opinion as me, and actually did something about it. Instead of using a monster ORM solution, he made his own library, called Sql2o  that helps with connection handling, transaction handling and batching, and then gets right out of the way.

Sql2o supports method chaining which can be nice for readability, and can automatically map tables to classes (using reflection) for simplicity. Sql2o is not an ORM, and it does not do any table or query generation for you. You have to make your database, and you have to write the sql queries to manipulate the data, but Sql2o helps with the rest and removes most of the JDBC boilerplate code that you normally end up having to write.

So now I get the best of both worlds. I have full control of the database and queries, and don’t have to write tons of boilerplate code to get things done. Combine that with using Play Framework and its built in caching, asynchronus job execution, and suddenly web application development with Java is pure joy.

Now go and remove Hibernate from your project, and start getting control over your database and queries! It will save you a lot of annotation fiddling and you will thank yourself a few years down the road when you have a better understanding of databases, and see some other developer swearing at his Hibernate-dependent project.

 

PS! If you are still not convinced, then have a look at this great video from Christin Gorman’s lightening talk titled “Hibernate should be to programmers what cake mixes are to bakers: beneath their dignity”.

 

39 thoughts on “Hibernate, just stop it!

  1. I thought you don’t use all the power of hibernate like cache or JPA, if you don’t like Hibernate you give a try to Ibatis or Spring SQL as good alternatives to hibernate they give you all power of SQL that you project needs.

    1. Alfredo: Thanks for the comment!

      My problem with Hibernate is the way it fools people into thinking that complex database issues are object-relational problems. Hibernate, JPA and a lot of other ORM’s keep you thinking about the objects and not the database, but that abstraction falls apart as soon as you have to tweak for performance issues. 🙂

    1. Thanks for the comment!

      ebean looks like a nice alternative, although I am not really that interested in the ORM capabilities. I just want something that simplifies the handling of connections, transactions and batching, so I get to use sql, without the boilerplate code that jdbc requires. 🙂

  2. Why not just use the Hibernate SQLQuery class when you want to execute raw SQL, and you can even have hibernate bind it back to your model? That is what I have done in the past instead of trying to create a complicated query with HQL.

    Hibernate really excels at doing CRUD work. I agree anything complex should just be handled through straight SQL.

    1. Hi, thanks for the comment.

      Regarding just using SQLQuery class and using the Hibernate binding, I feel that any project other than a simple throwaway thing usually ends up with one-to-many or many-to-many relations and propagating changes. This is when conforming to Hibernates way of thinking gets just as difficult or worse than just working with the database directly.

      That is my humble opinion 😉

  3. My comment with using Ebean (which is default on Play2 Java) is that it treats SQL as a first class citizen, allowing you to swap back and forth between the two easily.

    Its documentation specifically says “SQL is much better for a whole lot of stuff, you should just use it”. It lets you use it directly, load partial data back into an entity model and then spelunk from there, it has a fluid API and does instrumentation to keep fast. It also does auto-tuning of your queries if you aren’t use SQL which is crazy cool.

  4. Absolutely True!!! I agree 1000% with you. I mean look at the code annotations annotations annotations…everywhere. It looks so nasty and complicated with all those hibernate code…

    There is so much automation in Java code generation for hibernate that virtually everything is being generated through tools…. Although there already exists but why can’t these open source guys focus on designing an extensive gui based query builders to generate the most complicated queries.

    Hibernate is over hyped.

  5. This is how I typically break it down.

    Use ORM to map my object to DB model. Use the ORM for the basics
    – Create
    – Update
    – Delete
    – Simple Read by PK or UK.

    For all other finders I use my own SQL. My last implementation I used JPA with Eclipse Link and have been happy with it.

    I am about to start playing with EBean soon. Curious to see the experience others have had with EBean.

  6. I’ve seen many projects which have bad performance and did use Hibernate or JDO. I hate those technologies (along with JPA).

    After writing thousands of line of JDBC code I’ve realized how it could be done properly.

    After analyzing dozens of hibernate alternatives, I couldn’t find the one I liked.

    Finally I made fast java ORM framework and open sourced it at:
    https://code.google.com/p/fjorm/
    It is quite similar to ActiveJDBC, but I like mine more.

    Hope someone might like it.

  7. I agree that new frameworks are available that do a better job and are simpler to use than Hibernate and JPA. I recommend studying and using the one that fits your needs better (I’m using Ebean’s Play! Framework implementation, I really like the ActiveRecord pattern).

    But I disagree when you say Hibernate is not suited for big applications. It’s just that Hibernate focuses on Objects. In order to successfully work with Hibernate, one has do design the database around the objects, not the other way around. We are used to think of database entities and creating the objects to manipulate them in Java.

    I’m not saying this is bad design, it’s just different (and modern frameworks allow that).

    When it came out, Hibernate was great because it cut down a lot of the work that had to be done manually (as you said, there weren’t a lot of frameworks that did it well).

    The SQL abstraction allowed switching the database providers without rewriting queries, in a time where SaaS, SOA and cloud applications were still crawling (so you had to write your application to work with whatever database the clients had a license for).

    Due to its focus on Objects, things that are normal in SQL, such as partial column selections (select firstname, lastname from users), are a nightmare to do with Hibernate (using projections and transformers).

  8. I hope one day these so called S/W Architects understand this….programmers have a tendency to insert hibernate wherever they see a database.. 🙂

  9. AMEN, Brother!!!
    This whole movement that thinks “SQL is evil” is just baffling.
    The optimizer code for most modern databases is some of the most sophisticated code on the planet. Why spend a bunch of money on your database engine and then hobble it completely?

    My view of Hibernate and enterprise level relational database engines is this:
    Picture a huge, lumbering semi or tow truck dragging your Lamborghini behind.

    There you have it.

  10. You talk a lot of sh*t about Hibernate without saying anything about how much experience you have using it and other similar tools. It’s hard to take anything you say seriously given that I have no idea whether you picked it up once and then just looked around for other people’s opinions and reworded them or if this is based on solid experience and lessons learned personally. This is coming from someone who already doesn’t like Hibernate, so it’s not like I’m in love with it and just looking for reasons not to trust your article.

  11. John, I wrote an ORM back in the days when there was no such thing. So I know ORMs. I talk shit about Hibernate because Hibernate is shit. I know it’s shit because I’ve written software that does the same stuff Hibernate does, except without the brain damage.

    How bad is Hibernate? Let me list the ways…

    * Hibernate caching often *slows down* your program.
    * Hibernate session flush is ridiculously, ludicrously slow. As in, takes a full minute to flush a session that has a mere 30,000 objects in it. I ask on the Hibernate mailing list why it is so stupidly slow, they reply “well, it’s n squared problem, because we have to check for dependencies between each of the objects in the Hibernate session.” Oh. Really. So. Uhm, I know what the dependencies are between my objects. I don’t need Hibernate to know them. I just need Hibernate to flush my objects in the order in which they were frickin’ created, because that’s the order they need to be in, else I wouldn’t have created them in that order! Hibernate is *FULL* of little helpful things like that, which brings the other thing to a head…
    * Modern web sites are comprised of dozens of web servers talking to a database back end. Hibernate’s mechanisms for making sure that two sessions on different servers don’t modify the same object are full of fail. They throw spurious exceptions instead of doing something reasonable, and otherwise cause your program to collapse rather than do what’s expected.
    * And then of course, Hibernate’s performance as a whole sucks donkey dung. For example, if I want to do a join to get all the attributes of an item, Hibernate doesn’t let me go fetch just the attributes I need. Oh no. It’s none, or all! It’s either full-on lazy prefetch-nothing causing thousands of tiny queries to be issued, or so aggressive that it’ll fetch the entire database into memory and blow up my servers!

    Frankly, I’ve spent more time fighting Hibernate into doing what I need than I would have spent just using iBatis or something similar to write SQL.

    My final thought is that Hibernate is fine for toy web sites that see a few dozen users per day. But once you hit production and you’re talking web sites that see hundreds of thousands (or more) users per day, Hibernate sucks so bad that nobody — NOBODY — who makes real production web sites that serve millions users per day uses it. Nobody. Not Google. Not Facebook. Not Twitter. Not Amazon. Nada nobody zilch zero. Maybe if you don’t intend to grow your company into being the next big thing, you can live with Hibernate’s pathetic performance. But once you hit that scale, you’re not talking SQL anyhow — nevermind a ridiculously slow and clunky thing like Hibernate on top of SQL, which is like taking a Yugo and yanking off three sparkplug wires. It might run. But if it does, it’ll run so bloody slow as to be useless.

  12. Hello, Ricki! I remember back in the mid-00s when hibernate was the rage you were interested in it, alas, the project we were working on at that time did not call for it.

    (My goodness, can you believe it has been 10 years!?)

    I have also used Hibernate since then, and I have come to similar conclusions as you: too much effort trying to figure out why it does what it does; too much effort trying to get it to do what you want it to do instead; too much magic behind the scenes; lack of error messages to tell you what is wrong; and so on. (And did I mention the horrendously long start up times?)

    When the magic works as it is supposed to, everything’s zen. But when the magic does not work, it is hell.

    I think that the problem with Hibernate lies in the fact that it tries to do so much, that it does not do anything well. It can supposedly be used for taking an existing database schema which was designed without having ORM in mind, and build ORM on top of it; and it can supposedly also be used for taking class hierarchies which were designed without ORM in mind, and add an RDBMS underneath them; these are quite high aspirations, but they cannot possibly work for any non-trivial design, and the fact that hibernate tries to support these features makes it immensely complicated and clunky.

    What I am *not* convinced about though, is the necessity of SQL. I think there should be a way to treat the RDBMS simply as a persistence medium for an objectspace and therefore to not have to directly deal with the RDBMS (or RDBMS-related notions) at all. And mind you, I am saying this even though I am well versed with SQL and I do not have any problem using it.

  13. Interesting. A friend of yours wrote his own library to replace hibernate. So cool !.
    Let’s reinvent the wheel for every project or company.
    The advantage of hibernate is that it is providing decent performance for 90% of the projects and it is reducing the amount of time spent in the DAO layer.
    You cannot add value to a project if you write your own ORM every time….

  14. Good discussion and I’m glad to see that more developers are coming to the same realization that ORM’s are just one more tier to get in the way. Using SQL is really easy, and give me a developer who understands the domain business model first, and I’ll take them over anyone who is looking for a magic bullet with an ORM especially hibernate.
    in the simplest case, you can generate restful services for the all the crud operations you need. And the very concept of allowing hibernate to do joins is totally baffling to me… the database should do the joins! its what its built to do, with zero network latency and a very specialized optimizer built especially for the purpose of that specific flavor of database. Depending on a developers optimization hints at a generic layer, for non-specific dbms vendors, in the app server (with latency to the db), is madness. ORM’s were yet another dumb ‘left turn’ the software industry took in the 2,000s. And agree with you entirely Rikki – any business application is always going to have many-to-many’s … if it doesnt, your db model is almost certainly wrong. Has everyone really forgotten how to do logical and physical database design? Or are we still in the dark ages where the database was just somewhere for web developers to ‘stuff’ their objects? 🙂 Cheers, and thanks for having the nerve to stand up and say that just because thousands are doing doesn’t make it “right”!

  15. Very nice article. I’m able to relate completely to what the author is saying. From my knowledge Spring JDBCTemplate or any other ORM that uses SQLs is way more flexible without constraints and henceforth, reduces development effort and improves application performance.

  16. You clearly missed the point of an ORM. An ORM isin’t meant to fulfill general query needs, it’s meant to hydrate domain objects in order to process commands, not queries… COMMANDS! If you are using the Transaction Script pattern for your domain model then you probably do not need an ORM at all, but with a rich object model how do you expect to hydrate complex object graphs and perform dirty checking to save them back? Running your own custom ORM solution would be silly…

  17. This is in response to comments by Michael Belivanakis on April 16, 2015. I am not an expert on Hibernate, but I am curious about it. My remarks are basically related to the following comment:
    “What I am *not* convinced about though, is the necessity of SQL. I think there should be a way to treat the RDBMS simply as a persistence medium for an objectspace and therefore to not have to directly deal with the RDBMS (or RDBMS-related notions) at all. And mind you, I am saying this even though I am well versed with SQL and I do not have any problem using it.”
    Assuming that I have understood the comment correctly, here is my response.
    The discovery of RDBMS is of fundamental importance, for which E.F. Codd got the ACM Turing Award, “Equivalent” of Nobel Prize” in computer science. Relational databases industry is established around this discovery and has been enormously successful. There are deep reasons behind this success. Before Codd, people were doing precisely what you have alluded to – namely build persistence on data models that predate the relational model.
    The concept of relations has been around in mathematics for a long time. Codd’s contribution is in giving an algebra, a new language, for retrieval of data. SQL is rooted in algebra and that is its life line for ease of use in favor of users and achievement of efficiency in favor of the system – both at the same time – in a manner that does not burden a user. Because of algebraic identities absorbed into human intuition, a user has the ability to formulate a query “easily”. The system too, rewrites user query in a more efficient form. Such efficient forms themselves can lead to 10 fold, 100 fold, …, improvement in performance without user intervention. Then the system considers stats on data, database schema, strategies for execution of operators, and indexes to generate diverse plans and estimates their cost. Then it produces the code for the cheapest plan and executes it. As profile of the data changes so can the plan. A strategy for such optimization would be bewildering for users to code in their Java programs. Consider this: the query optimizer in major database systems is estimated to require 40 to 50 person years of work. All this tells us SQL is here to stay. (BTW, HQL is also a derivative of SQL and algebraic at its core.)
    This gives rise to the so called impedance mismatch problem. Java is an imperative language where a user thinks in terms of variables, tied down to memory locations, and assignment statements. Furthermore, Java is object-oriented and offers a rich environment. SQL, on the other hand is algebraic. The two paradigms are quite different but the problem is that we cannot get rid of either. This is why we must create hybrid solutions where programs have an imperative (Java) personality as well as an algebraic personality – hence the impendence mismatch. There is good theoretical evidence to suggest that neither Java nor SQL (or any of its derivatives) can absorb the other hence the impedance mismatch is here to stay.
    This does not mean that either of the two (Java or SQL) can lean in the direction of the other. Hibernate is an attempt to let the HQL (derivative of SQL) lean toward Java. An attempt in the other direction was made under by the ODMG (Object Data Management Group) in 1990s. I think that is the smoothest possible solution to date to reduce the impedance mismatch. O2, a database system product together with OQL (Object Query Language), was developed and marketed in early 1990s. This product disappeared shortly thereafter because of corporate acquisitions.

  18. You are absolutely correct. Anyone who has worked on production systems involving thousands of table can only wish Hibernate all the very best. I had a chance to use Hibernate and I am so glad i did not for exactly the same reasons that you describe. The minute you get into complex relationship I cannot understand how this will scale. At the end we just wrote our wrapper over JDBC (something like iBatis) to reduce programming effort and that was it. I am so thankful to you for calling this out. I fear however that most people may not agree and I would only base it on lack of understanding and blindly picking up the next trend

    Deepak

  19. This is what I’ve been thinking for many years. When I first learned hibernate I thought it would somehow be better than what came before. It just seems to encourage developers so sick up junk into the database without having to think of what they’re doing. There’s no substitute for leaning proper database design. Also, I suggest the complexity of relational databases isn’t the issue. Rather it’s that the OO concept really isn’t as great as it’s cracked up to be. It doesn’t map to real world problems OR relational databases too well. There’s a lot of shoe horning involved.

  20. Well for me the story is somewhat different: SQL is the first abstraction over data representation in files that we delegate to the DB.
    When we write a query we transfer to the DB the responsibility to convert it into “a plan” to access the various tables it involves.
    Even SQL queries can give you problems when you have complex data structures and become very slow.
    The point is that we use SQL since a lot more time and we learned that data access statistics are not always enough and sometime we use “tricks” to deal with it, like oracle hints or subqueries, or anything that changes the data access path.
    But all these go against the idea of SQL being a DSL were you say what data you want and not how to get it.
    The point with any ORM is that it simply tries to map an object model, intrinsically tree like, into a relational model, intrinsically relation-based.
    There is no way you can make this dichotomy go away, and hence there will be cases in which an ORM will help making this mapping useful, other cases in which the advantages will come at the cost of having to reason on how the mapping affects the underlying sql and hence change the mapping in order to don’t screw the sql, and cases in which it will be better not to use an ORM at all.
    Bu this does not turn ORM in “shit” per se, simply it is not a silver bullet.

  21. I ‘ve “inherited” a project that started by two other colleagues. They’ve used Hibernate for everything. The project was already big when I’ve joined the team but they didn’t have any real data to test the performance. Now, both of them are not working in the company anymore and I am having nightmares with the inefficiency of Hibernate now that the project is running in real enviroment. The problem is that I cannot rewrite the whole thing since it is huge. I would try to stay away from using any ORM in the future. Plain SQL and JDBC are good and strait forward.

  22. Any ORM like Hibernate, the part of Spring handling database operations suck because:

    1. They are all ORM -why use objects to save data when we can save data directly which also increases the preformance speed? JDBC (java default) and knowledge of SQL syntax is enough!

    2. They are all based on java API reflection to access member class names, make db table column names out of it etc. This also affects the performance speed even if all this reflection related stuff are usually done when application starts (which also make
    application to start-up slower).

    3. Using any framework to do stuff you usually do using JDBC/SQL inherently leads to performance drop because those framework “translates” all the stuff to JDBC/SQL internally.

    4. When something goes wrong you must be a framework expert to debug…its like learning a new script language. That’s because framework control JDBC/SQL not you.

    That’s why real application like scientific ones never uses frameworks. It’s all about efficiency and control. Again, use java pure language and learn it well and not rely on different frameworks to do stuff you should do. JDBC/SQL its all you need to do DB stuff. Also use polymorphism to create useful class templates and you are all set. Finally, if you have not the time to develop your template to do DB stuff, search for free JDBC/SQL solution but never use frameworks!

  23. As I wrote in my book, High-Performance Java Persistence ( https://leanpub.com/high-performance-java-persistence/read_sample ), Hibernate offers the following advantages:

    – extended identifier generators (hi/lo, pooled, pooled-lo)
    – transparent prepared statement batching
    – customizable CRUD (@SQLInsert, @SQLUpdate, @SQLDelete) statements
    – static/dynamic entity/collection filters (e.g. @FilterDef, @Filter, @Where)
    – mapping attributes to SQL fragments (e.g. @Formula)
    – immutable entities (e.g. @Immutable)
    – more flush modes (e.g. FlushMode.MANUAL, FlushMode.ALWAYS)
    – querying the second-level cache by the natural key of a given entity
    – entity-level cache concurrency strategies
    – (e.g. Cache(usage = CacheConcurrencyStrategy.READ_WRITE))
    – versioned bulk updates through HQL
    – exclude fields from optimistic locking check (e.g. @OptimisticLock(excluded = true))
    – versionless optimistic locking (e.g. OptimisticLockType.ALL, OptimisticLockType.DIRTY)
    – support for skipping (without waiting) pessimistic lock requests
    – support for Java 8 Date and Time and stream()
    – support for multitenancy

  24. I’ve only been programming in Java for about 8 months, but came from a role where I used SQL often. When I was introduced to Hibernate I was not a fan. I felt like I was not in control of my queries. I often knew the query that I wanted to write, but was stuck figuring out how to translate it into Hibernate code.

    More recently, I used Sql2o for a project and loved it! It was a perfect middle ground between JDBC and Hibernate as you described – I had control of the SQL once again, but didn’t have to write as much boilerplate code.

    For what a new developer’s opinion is worth, I hope that there other devs don’t just choose Hibernate because they assume it’s the “best practice”, but consider its strengths and weaknesses as well as those of other frameworks, like Sql2o, as well.

  25. Hibernate roll complex sql queries in a mess of xml files, where any maintenance of the project became a nightmare. Change a DAO and you can risk your life. Please, give me back my SQL language!

  26. It’s been years since this article was written but I have a question regarding big projects.
    How would you handle an update/insert in an object graph that is 5 levels deep with possibly thousands of nodes? Are you able to automatically create SQL statements with proper INSERT or UPDATES depending on the existence of previous objects? How do you know what queries need to be executed first in order for the database update to be done properly (foreign keys not missing etc). Hibernate is used for its ability to keep track of such things. Everyone knows SQL but managing such object cases is what Hibernate is for.

    Using Hibernate to avoid writing SQL is a junior’s choice. Using Hibernate to leverage its entity management on a big project is a senior’s choice. Hibernate isn’t for big projects. It is for projects with big databases.

    Chris Mamounis says hi.

    1. Q: How do I handle an update/insert in an object graph that is 5 levels deep with ORM?
      A: You don’t. Period.
      For ORM to work you MUST treat your DB as a dumb data grave and have all intelligence and complexity in your application. This also means simple flat data structures where tables are storing the answers that you need at worst only one or two joins away. In a pinch, for one off non-time critical, queries one can use more complex data queries, but that should not be the bread and butter of your application.
      Using an ORM places much, much more effort on data Architecture and your domain model to be clean and simple. You can no longer bend the DB to your wills. But being forced to use a smart and simple data model actually frees you as a programmer. It enables you to focus your attention on delivering value through the service of your application. Data is just a means to an end.
      And this I believe is the dichtomy between Hibernate haters and Hibernate lovers. The Hibernate haters just hack around in data without really thinking about domain models and delivering value through service, while for the other group data is just a means to an end of delivering value through a service.

Leave a Reply

Your email address will not be published.