I’ve been spending quite some time working with both Hibernate/JPA and MyBatis, and as such, have been better contrasting the problems of the former with the latter. I love MyBatis. I can also say that I’ve worked to a good extent with Hibernate/JPA to know i’m not just engaging in some sort of mindless smear campaign.
The problem w/ Hibernate/JPA, i’ve felt is never really about the framework. It’s very sound, it’s like the mother-of-swiss-knives in the ORM space, and unfortunately, it entails an incredible amount of learning. A learning which I personally feel is never completely undertaken when you see people who want to adopt it to avoid entangling in the complexity of SQL. That’s a first-order joke. The complexity of SQL is like a linear iteration routine compared to a recursion routine over a random XML structure as symbolised by Hibernate/JPA. And more often than not, when faced with the arduous task of making sense of the Hibernate/JPA documentation, people inevitably cut corners. I did too! There’s just too much involved to unleash the beast within the beast that is Hibernate/JPA.
Some of the core abuses of the Hibernate/JPA framework that come immediately to my mind –
- Annotations – there is a limit to which logic can be encapsulated within annotations, but here it seems like in an effort to achieve no-boilerplate-code zen, the team’s gone a bit overboard. The annotations which stand out in this case – Cascade, ManyToMany, ManyToOne, Transactional. Some of these should be handled through implied reflection, and the others should simply not exist. Developers might as well know wth they’re doing!
- Transactions – though mentioned before, but this deserves another mention. Transactions need to cover DML queries, and usually these operations constitute a small fraction of all operations. In order to avoid writing 4-5 lines of boilerplate code, the adoption of annotations makes no sense. Shouldn’t DML’s represent the most critical part of the application, so what’s the harm in expecting the developers to know what they really need to do
- Query cache and Secondary cache – i’m sure the intent behind this is novel, but boy it’s darn complicated to wrap your mind around these. To grasp how to control these caches is a herculean task. I still am not sure why isn’t it simply better to develop support for plugging in external caching frameworks?!
- Persistence context and Lazy loading – i think this one takes away the cake. the biggest rant i have against this is that the documentation presents the practice of lazy loading as the smartest thing a developer can do, when in reality using it is like walking a tight rope! Of course, lazy loading associations is a good thing. But shouldn’t the flexibility and responsibility of controlling this lie with the developer? Once a field’s annotated lazy, then that’s all it will ever be! Now of course, you could simply access a lazy attribute to load, and not access it to keep it lazy. But is that an intuitive way to go about things? Pointlessly access attributes to load them before the persistence context’s session closes for the particular operation?
- Handling lookup tables – if you’ve got a normalised schema and there exist tables which hold nothing more than IDs of different types mapped to each other, then the way to do this – you have to create an extra class, annotate it as embeddable. Why should I be forced to create a new class just to handle lookups?!
- Advanced SQL query support – when was the last time you tried to do a self-join on a table? Now why would one need to do so? well say, you have a students table having student names and marks. if you want to find out all the students who secured more marks than the average marks, how would you do it?
- HQL – point 6 inevitably leads to this, and this is where I really don’t get it. If you’ve created a framework to abstract something, why to introduce something awfully similar to cover up all the bases? not even considering the performance impact, this looks like a classic case of a leaky abstraction. true – it allows users to write code which will work exactly same across databases – but really, how hard is it to instruct all developers to abstain from using DB vendor specific sql constructs?
So why do I like MyBatis – of course, besides the many articles which have measured the two frameworks like this one – I just feel that if you know SQL, or can set aside a little time to do so, MyBatis is the most transparent framework to help you achieve the sweet spot w.r.t database related applications. I know you guys might be faced w/ a decision along these lines somewhere down the road, so I hope this would help you out.
In conclusion, I believe that the problem doesn’t lie with Hibernate/JPA, but with the people who use it and the amount of time required to be invested to make it working for a high performance database-based application. A possible solution could be for the Hibernate team to seriously consider the release of a no-frills, pure and simple ORM framework. But then, MyBATIS is already there, and I guess to do so will just validate MyBatis’ approach, and people will inevitably raise doubts about Hibernate’s existence.