This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
I have an instance where I want to retrieve only a partial object graph, but can't seem to work out how to do it.
Here is the scenario:
I have an Order class that contains many products. At times, I want to retrieve the order and ALL of its products, and other times, I want to retrieve the order and only ONE of it's products. The example below is a simplification of my REAL graph where the Product class also contains several one-to-many relationships, thus the reason why I only want ONE product so that I can cut down on the amount of data that I retrieve at a given time.
Below are my classes:
So, my question is how can I do it? I have tried creating a criteria object as shown below. Hibernate creates the select statement correctly, but then immediately creates another select statement that retrieves ALL of the products, thus nullifying the first select. Is there some way of telling hibernate not to try to eagerly retrieve all of the products? And if I set the FetchType to lazy, even then when I call getProducts( ) it retrieves ALL of the products.
Fetching should always be use case/query driven and not mapping driven.
In your mapping of Order to Products you have fetch set to Eager, and therefore when you get an Order it will always have Products. If you remove the fetch, it will fetch by default lazily, meaning from now on you get an Order you get no Products. Now in the use cases in which you need Products you just create a query in which you set it to eagerly fetch. With HQL is as simple as "Select o From Order o left join fetch o.products"
If you use the Criteria object, it has a method called setFetchMode(FetchMode fetchmode) and you can use the FetchMode enum and use FetchMode.JOIN
I hope that helps.
Now if you don't want an order without any products, and you definitely know for sure your use case needs one and only one of the Products, then you are going to have to load/get the product yourself and add it to the Order's product Collection, to keep the database access to a minimum.
Thanks, Mark!! That makes sense. So one more question: If I retrieve the Product separately, and add it to the collection in the Order class, how do I tell hibernate not to try to retrieve the all of the Products when I make a call to the getProducts( ) method? If the FetchType is set to LAZY, when I go to get the Product list, it again tries to retrieve the entire list and populate the collection.