I *am* big on OO; however, I am a Hibernate newbie, am under a deadline (who is not?), and the whole cascading business and all the complexity under the hood just drives me nuts. What, I have to keep an open Session or pre-load the whole structure?? An open session might not be a bad idea (it's a Swing 2-tier), but then how do I refresh stale data? How do I recover from HibernateExceptions? That means no lazy loads.. hmm.
So, after spending a day debugging an umpteenth mind-boggling hibernate exception, I cut the whole complexity off. I got rid of all relationships between entities. I.e. an Employee.getSupervisor() now returns a String id, not another Employee. If I ever modify my data objects to return complex types, I do it either in @Transient methods or in DAO.
I mean, instead of
I now write something like
Not as intuitive, but it can be always refactored away some place, and the work of hand-coding it is, to me, worth the tons of mind-boggling exceptions I was getting, not to mention performance tuning of having acidentally loaded the entire database into memory.
Yes, that makes my model a bit harder to reverse-engineer (if I don't adhere to some sort of discipline with transient properties); but then, my model layer mirrors the underlying tables very closely, and whoever needs to make sense of it just has to look at an ERD. My ERD is very intuitive.
Has anyone been there before? Is it too drastic? Is there a less radical solution to that end? Will I want to redo it as I become more familiar with Hibernate?
I think you're going to want to redo this when you become more familiar with Hibernate. Relationships between objects are useful in Hibernate especially when it comes to writing queries that are more than findById.
The best place to start is either by reading the documentation and examples at (Hibernate Reference) or by reading Hibernate in Action.
And do the examples because that is the best way to see it working properly.
Also, if you've got specific questions when you start putting your relationships back in - just post on the forums.
Thanks. OK then, here is a question: I have an Employee tree, of 1,000,000 employees (I don't, but that's just an example). Every emplyee has a supervisor and subordinates. I have short-lived sessions. How do I traverse this structure without loading the whole thing into the memory at once?
I do have relationships beyond findById(), I hand-code them, sometimes as org.hibernate.SQLQuery. There are only two or three like these so far.
That depends on what you need to use it for. Do you need to traverse the structure to insert something in place in the structure or are you traversing the structure for display purposes?
With large datasets you need to use Hibernate carefully because you will run out of memory quickly. The best practise is to use an Iterator or ScrollableResults to load up one object tree at a time and evict the object (and usually flush the session) as soon as you are finished with it.
Another trick is to load only the parts of the Employee that you need for the process. For example, if you need the Employee name and the related Subordinates and Supervisors but not all of the Employee's Addresses or Tasks (for example) then write your query to exclude the items you aren't going to use. This will speed up your processing and help you keep within your memory limits.
Although you mention that you have short lived sessions. Is there a reason for this?
There are ways to get around this too but I'd need more information about what you are going to do with this large set of Employees before I could suggest what would be best in a case with short sessions.
Also, if you post the relationships that you have done by hand I could work out if a criteria or hql query would indeed be simpler than a sqlquery.
Hope that helps,
Did Steve tell you that? Fuh - Steve. Just look at this tiny ad: