Saturday, May 13, 2006

Why can't Hibernate just load objects on demand?

Today I was reading: Why can't Hibernate just load objects on demand?
I find some of its affirmations interesting (I realize this is kind of a sensitive topic, but I just don't feel that the information there is convincing enough, specially if you have used other ORM that do have distributed non-transactional lazy loading:


If Hibernate would, hidden from the developer and outside of any transaction demarcation, start random database connections and transactions, why have transaction demarcation at all?



That really is a very good question, what exactly it is so good about having transaction demarcation? (wouldn't it be better to have "automatic transactional demarcation"?) like this:


Customer newCustomer = new Customer(EcoSpace);
newCustomer.Name = "Air Software Ltd";
newCustomer.Telephone = "+44 (0)121 243 6689";

TelephoneNumber alternateTelephoneNumber = new TelephoneNumber(EcoSpace);
alternateTelephoneNumber.Name := "Home number";
alternateTelephoneNumber.Number = "+44 (0)121 999 9999";
newCustomer.ContactDetails.Add(alternateTelephoneNumber)

EcoSpace.UpdateDatabase();

Wouldn't it be better, if, as we have the Session, and the transactions...we could have an equivalent to ECO's EcoSpace?

(Important Note: I am NOT saying ECO is better than NHibernate, in fact I had to choose between the two for a project, and IMO NHibernate was a better choice, because its mapping capabilities for legacy databases are far superior, and its lower level session/transaction base API gave me more control, and HQL is IMO more powerful than OCL... but not all projects need that level of control, and... specially for new projects that do not need to interoperate with legacy apps, or that will have full control of the database ECO could be a much better alternative because of its easier to use API with automatic transactional demarcation and non-transactional lazy loading)


What happens when Hibernate opens a new database connection to load a collection, but the owning entity has been deleted meanwhile?


I guess in that case it should throw an exception... but I don't see this a justification for transaction demarcation... IMHO the same problem can happen with regular "manual session opening an closing"

(Note that this problem does not appear with the two-transaction strategy as described above [in the question Can I use two transactions in one Session?] - the single Session provides repeatable reads for entities.)


Yes, but that also means I need to have a session and transaction open during user think time...

Why even have a service layer when every object can be retrieved by simply navigating to it?

That is really a problematic question... in fact... the question is my point exactly... why should I bother having a service layer if every object can be retrieved by simply navigating to it? IMHO not having to build a service layer sound like a good thing... doesn't it?


All of this leads to no solution, because Hibernate is a service for online transaction processing (and certain kinds of batch operations) and not a "streaming objects from some persistent data store in undefined units of work"-service. Also, in addition to the n+1 selects problem, do we really need an n+1 transaction and connection problem?

So... that means... that if we want distributed non-transactional lazy loading we should build a streaming objects from some persistent data store in undefined units of work service? is that what other ORMs (like Borland ECO or Apple's EOF are? who draws the line? I know that the owners of Hibernate are free to choose, but is this decision theoretically supported? I'd like to know how...)


The solution for this issue is of course proper unit of work demarcation and design, supported by possibly an interception technique as shown in the pattern here, and/or the correct fetch technique so that all required information for a particular unit of work can be retrieved with minimum impact, best performance, and scalability.

Yes, but OpenSessionInView is only a good idea if you are building a web application.. and if you want only one transaction per request/response cycle... if you UI deviates from that... then it is no longer such a good idea...


Note: Some people still believe that this pattern creates a dependency between the presentation layer and Hibernate. It does not...


Well, then, why OpenSessionInView isn't a good idea for interactive UIs in smartclients? isn't changing form ASP.NET to WindowsForms a change on the presentation layer? so.. If i built my application to share its business logic between a WindowsForms and an ASP.NET presentation and I am going to have problems... then that means I am tied to a particular presentation layer... isn't it?


No comments: