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?
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:
- http://stackoverflow.com/questions/8678865/sql-to-hql-conversion
- http://stackoverflow.com/questions/12098814/hql-left-join-cracks-even-with-easy-examples
- http://stackoverflow.com/questions/267085/converting-sql-to-hql
- And you can 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:
- http://stackoverflow.com/questions/179259/why-does-hibernate-try-to-delete-when-i-try-to-update-insert
- http://stackoverflow.com/questions/3316070/hibernate-why-does-a-change-of-bag-lead-to-strange-adds-and-deletes-in-the-data
- http://stackoverflow.com/questions/11081133/hibernate-why-insert-operation-is-performed-last-in-this-case
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:
- http://blog.jooq.org/2011/09/07/why-did-hibernatejpa-get-so-complex/
- http://blog.jooq.org/2011/10/25/annotatiomania-next-level-jpa-and-jaxb-combined/
- http://blog.jooq.org/2011/11/24/next-stop-on-the-annotatiomania-train-fetchgroups/
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 {
TableAlias<User> userAlias = beanSession.createTableAlias(User.class);
User user = userAlias.proxy();
SQLBuilder sql = new SQLBuilder(userAlias);
sql.append("select ");
sql.append(userAlias.columns());
sql.append(" from ").append(userAlias.tableName());
sql.append(" where ").column(user.getName()).append(" like ?");
sql.append(" and ").column(user.getId()).append(" > ?");
sql.append(" order by ").column(user.getName()).append(" desc");
stmt = SQLUtils.prepare(conn, sql.toString(), "M%", 11); // varargs for params
rset = stmt.executeQuery();
List<User> users = new LinkedList<User>();
while(rset.next()) {
User u = new User();
beanSession.populateBean(rset, u);
users.add(u);
}
System.out.println("Total number of users loaded: " + 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, 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.
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.