MentaBlog

Simplicity is everything

Hibernate is more complex than the problem it tries to solve

 |  5 Comments

Relational databases have been around for a long time and there is nothing too complex about them. Any medium programmer should be able to learn how to write SQL in less than a day. Indexes, joins, transactions, caching, lazy loading are not complex topics either. Despite all that, Hibernate has become the de facto standard for writing database access code in Java. In this article I try to explain the drawbacks of Hibernate and how things can be done differently.

When I first met Hibernate, these were the questions that my brain could not stop asking me:

  • Why do I have to learn a new query language when there is SQL?
  • Why the Hibernate learning curve is so big?
  • Why does Hibernate do so many things automagically that I cannot control or understand?
  • Why is so hard to make sense of the Hibernate mappings through annotations?
  • Why a programmatic approach through a fluent API or DSL is not offered?
  • Do I really care about database independency?
  • Do people really think that without Hibernate you have to write a lot of SQL and JDBC boilerplate?

Ad: Coral Blocks: cutting-edge, ultra-low-latency, zero garbage Java components: CoralReactor, CoralLog, CoralQueue, CoralThreads and CoralBits.


Below I will try to answer these questions:

Why do I have to learn a new query language when there is SQL?

If you never heard about SQL you can probably learn HQL or Criteria, the query languages of Hibernate, without a problem. But if you know SQL there is little motivation for you to learn those new query languages. The gain is small plus everything you write will be eventually converted to SQL anyways. I can see some people saying that HQL is more objected-oriented and Criteria is entirely done with objects, but that alone does not justify using Hibernate and its complexity in your projects. At the end, you will be better off by speaking directly to the database using its native SQL language so you can understand and take control of your code. Below are some examples of people struggling with HQL when they already know SQL: (you can also click here for the Google full list)

Why the Hibernate learning curve is so big? Why does Hibernate do so many things automagically that I cannot control or understand?

When I check the Java questions in a forum or discussion list I can’t help but notice that a lot of them are about Hibernate. Hibernate can have some qualities but “persistency that just works” is not one of them. It often does not work or works in ways you could have never imagined. I must agree with what Pascal Thivent says here: “Hibernate in the wrong hands can be a real disaster!“. Below I list another examples of Hibernate surprising behaviors:

Why is so hard to make sense of the Hibernate mappings through annotations? Why a programmatic approach through a fluent API or DSL is not offered?

If somehow the relationship between your entities are not working as expected then all you have to do is play with those annotations and hope that it will work the same way you would hope for a better image by hitting the top of your TV in the old days. Annotations is just a little less bad than XML, but not much. Its complexity can easily get out of control in what is known as Annotatiomania, a term coined by Lukas Eder in his blog series below:

Do I really care about database independency?

Your database is something you choose in the very beginning of your project and then stick to it to the very end. There is no point of being paranoid about database independence, not even for automated tests executed against a different database engine. Plus some good in-memory databases like H2 has compatibility with other databases so you can run your queries without a problem. Even if you run into a compatibility problem that just tells you that you should not be running your automated tests against a different database.

Do people really think that without Hibernate you have to write a lot of SQL and JDBC boilerplate?

People who think like that were probably so busy learning Hibernate that they missed the alternative movement of query builders or worse, don’t understand the wonders that reflection, proxies and abstraction can do to simplify things. Check the code below which performs a SQL query:

Connection conn = getConnection();
BeanSession session = getBeanSession(conn);

PreparedStatement stmt = null;
ResultSet rset = null;

try {

    StringBuilder sql = new StringBuilder(1024);
    sql.append("select ");
    sql.append(session.buildSelect(User.class));
    sql.append(" where status = ? and deleted = ?");

    stmt = SQLUtils.prepare(conn, sql.toString(), Status.GOLD.toString(), 1);

    rset = stmt.executeQuery();

    List<User> users = new LinkedList<User>();

    while(rset.next()) {
        User u = new User();
        session.populateBean(rset, u);
        users.add(u);
    }

    System.out.println("Total de usuários carregados: " + users.size());

} finally {
    SQLUtils.close(rset, stmt, conn);
}

So what is the alternative?

It is any non-intrusive framework that gives you control without complexity through abstraction. I am going to suggest MentaBean, of which I am the creator, but there are also others like jOOQ, myBatis, Ollin, Ebean, etc. MentaBean is a straightforward ORM (Object-Relational Mapping) framework for those who want to work with SQL without the JDBC boilerplate. Differently than other ORMs it keeps the magic to a minimum so you always know what is going on under the hood. MentaBean automates CRUD operations without any SQL, but it will not make you learn a new language when you need to query. Instead it helps you build your queries using SQL without the boring parts. It also does the object-to-database mappings programmatically through a fluent API. With MentaBean you don’t have to worry about XML programming or Annotation hell because the mappings are done with Java code. So if you like and understand SQL and are tired of the huge learning curve and unpredictable behavior offered by other complex ORM frameworks you should try MentaBean for a simplicity break.

Its website is very straightforward with examples and explanations: http://mentabean.soliveirajr.com

Conclusion

I expect that some people will say that I just don’t get the benefits of Hibernate and that I don’t know how to use it. Although there might be some truth in that statement, as a matter of principles no benefit is justified with the drawback of complexity. A solid foundation focused on simplicity is what guarantees the success of a software system in the long-run. Hibernate is so big, powerful and complex that it can easily get out of control. If the focus is simplicity and control, other better alternatives like MentaBean should be considered.

 

5 Comments

  1. Working on my 5th Hibernate project now, I tried drinking the Hibernate/JPA Kool-Aid for years. However lately I’m finally waking up and coming to the same conclusions:

    1) The bytecode-fuddling lazy loading design is broken in terms of class responsibility – an entity shouldn’t really be coupled to the persistence mechanism and yet that is exactly what Hibernate is doing under the hood via cglib. Even though this coupling is hidden it is still there and causes way too much unexpected behavior. There is no need for all of this obfuscation that came out of someone’s master’s thesis on how “great” AOP is (even though it is totally impractical, un-debuggable and unmaintainable).

    2) One Hibernate/JPA call can sometimes calls a dozen SQLs needlessly, requiring hours of debugging and consolidation – wasted time doing performance optimization that would not be required if the SQL is explicitly developer controlled.

    3) Hibernate (within its own design paradigm) should automatically do eager fetching using joins. After all, that is one of the main points of using it. However, it sadly does not and usually chooses the poor performance option of doing many n! number of ridiculous SQLs instead.

    4) Code reliability is worse than hand-coded JDBC – in that you can’t rely on a service class called with the same parameters to behave the same every time. Making one change in place X ripples to code Y, and now you have LazyInitializationException’s, or it can’t find the session for whatever reason. These problems can of course be dealt with, but usually only after wasting lots of precious time.

    5) Spring/Hiberntate proponents often get around all this mess using Session-In-View, an evil anti-pattern that now makes your code impossible to optimize since SQL is being called all over the view. Congratulations.

    6) Proper transaction management is usually lost in all the confusion.

    7) Even if you have someone on your team who understands all of this, 80%+ of the developers don’t and never will. Nor will they ever watch the SQL output while testing. So you essentially end up with slow code (which is a problem with or without Hibernate, but Hibernate certainly does not solve it and essentially makes the problem worse).

    I was looking at Apache DBUtils previously but that one doesn’t seem to support joins which makes it seem kind of worthless.

    MentaBean looks interesting. Seems like much of the BeanConfig stuff could be automated using startup reflection though.

  2. Pingback: Kari's World » Blog Archive » Mantra of over engineering

  3. You raise some good points with respect to Hibernate, its learning curve and it being overly complex. I have been fighting the learning curve over the last 8 months and seeing very little value in return.

    In addition to your comments, I have also found that Hibernate has very poor handling of Many-to-Many relationships where the join table is not a simple 2 column id to id mapping. These situations generate null pointer errors deep and in the Hibernate code and yet, in research, this is “expected” in such situations according to people using the framework. To me, a framework should be doing the checks and converting the invalid uses to human readable errors instead of turning API usage into a debugging exercise. In far too many cases, you have to dive into hibernate to find out what it does not like because the error reporting is non-existent or obtuse.

    With respect to your API, Mentabean, I would be interested to understand what you intend to be the advantages over something like Apache Cayenne?

  4. This post is right on target. Some 20 years into this and having gotten into a sizable JPA Annoations based project, the full OO implementation just tries to be all things to all people – hence the bloat.
    The biggest frustration is the assumption of JPA as a defacto standard (including JPQL, which is grossly immature in comparison to SQL, which some organizations do not even allow). Considering that these are Java-only frameworks, it is almost laughable to call them defacto standards when Java represents only a fraction of development languages. Lastly, it is clear that such frameworks are the result of trying to satisfy an increasingly immature group of developers considering that only a few years ago, the Java/EE community was push EJBQL and variations thereof as the ‘defacto standard’ at that time – only to freely admit later that they were horrible and consequently abandoned. So too shall JPA one day go the way of the Edsel.

  5. It is quite refreshing and consoling to find articulated post like yours, about this overwhelming hype and propaganda on use of Hibernate in Java development.

    I have completed 2 projects using that nonsense (where “nonsense” is most decent and most polite word that can apply) and I can absolutely agree with every single point in your post, as well as with most of the comments (e.g. with Jake, about many-to-many “handling” or rather, mishandling by Hibernate).

    I did not try your framework (MentaBean) as an alternative to Hibernate, but I was working with iBatis (now MyBatis) and in comparison with Hibernate nonsense, iBatis/myBatis is doing exactly what ORM suppose to do i.e. removing needs to boilerplate code and seamlessly handling interfacing with RDBMS, without trying to play some sort of Artificial Intelligence package, as Hibernate pretends to do.

    Even Spring JDBC with all its simplicity and straight-forwardness is better approach to ORM than Hibernate.

    It is huge mystery to me why that pointless, unpractical, unreliable and utterly misleading piece of bloatware is constantly getting such big acclamation and propaganda during past 5-6 years?
    What stays behind it??
    I cannot believe that so many software engineers around this planet cannot see that Hibernate is something totally wrong, that it is all that good software shall never be nor do.
    Who da f* is promoting that piece of nonsense so aggressively through the Java community???

    Regards to author and all the commentators.

Leave a Reply    (moderated so note that SPAM will not be approved!)