Turns out there are many details that we did not think as important when we glossed over the Hibernate manuals.
The biggest problem is that the manual is more of a tutorial rather than a reference. We had difficulty doing things that are not covered in the manual, such as defining a 1-1 relationship: how to make sure that both entities share the same id. Another example: what does
Session.lock(obj, Lock.UPGRADE)
do to an entity without a version field (how can it know that it is performing an upgrade when refreshing from the database without the version information in a clustered environment). We spent a lot of time figuring out the best way to adopt Hibernate into the system. There is even a time where we spent a whole week diagnosing Hibernate-related problem, then after that another week to refactor existing code in light of a better understanding on Hibernate.
The refactoring could go on for ages because as we understand Hibernate more, the urge to refactor/clean up becomes more prominent.
One day, we woke up and realised that we have been spending too much time tinkering with the system instead of building it. We decided to make a cut, a non-optimal cut, and proceeded to continue what the client paid us to do.
(originally from http://microjet.ath.cx/WebWiki/LosingOnesIntention.html)