Here's a problem that I ran into with developing in Java using struts and hibernate with lazy loading.
In order to keep the intrinsics of Hibernate out of your Action class, you use the DAO pattern to do all your data access (including opening and closing the hibernate session). The problem is by the time the function returns from your DAO to your action class, the session is closed. You can get around this problem by using a request filter that opens the session at the start of the request and closes it after the response is generated.
Now to my point. "Best Practices" dictates that any Enterprise App (even desktop) should use that same architecture (MVC with a separate layer for Data Access).
Everything works peachy keen if you aren't using lazy loading. But what happens when you want to avoid loading all the orders and order lines for a customer into memory everytime you want to update his/her address?
One solution is to make your top level data in your domain objects a summary object. For instance a customer's top level data would be things like his name, address, customer number, etc. This all gets put into the summary object and in the CustomerSummary's mapping its lazy loading is set to false.
Make sure you do the same with all of your Domain Objects that have subgraphs. (So your order objects that have line items associated with them gets order summaries).
Now for the Customer object itself, you have the summary as a property and you have the usual collections like orders, payments, etc.
The mapping for your Customer object would be linked to the same table as the CustomerSummary object but the only item you map from the table is the id mapped to the primary key. You do a 1 to 1 mapping to the CustomerSummary object and then do the one to many mappings for all the collections (mapped to the summary objects). Of course the Customer object sets its lazy loading to true.
Your DAO can now have functions that return CustomerSummary objects or OrderSummary objects. When you want to get the detail on the orders for a customer it can return a List of OrderSummary objects by returning
Code:
(Customer)ISession.load(Customer, tmpCustomerSummary.id).orders
"Okay that's fine and dandy...but what about reporting, when I want to load everything and return it from the DAO for processing."
In this case you should use a Data Transfer Object (different from a Domain Object) that knows how to load itself from the Domain Object. So in essence I'm basically recommending that you triple your objects to follow this technique.
The benefits are clear however. You get the benefit of lazy loading without anything outside of your DAO dealing with Hibernate sessions.