-
1. Re: eager vs. lazy fetching
mazz Feb 22, 2007 8:15 AM (in response to eiben)You cannot programatically set the eager/lazy setting. You either set it to EAGER and have it always fetch, or you set it to lazy and for those things (like servlets) that need to force an eager fetch, they would need to call into some SLSB or some such thing that performs a FETCH JOIN query.
-
2. Re: eager vs. lazy fetching
eiben Feb 22, 2007 8:31 AM (in response to eiben)"mazz@jboss.com" wrote:
You cannot programatically set the eager/lazy setting. You either set it to EAGER and have it always fetch, or you set it to lazy and for those things (like servlets) that need to force an eager fetch, they would need to call into some SLSB or some such thing that performs a FETCH JOIN query.
OK, kinda feared something like that. How do I do FETCH JOIN query? -
3. Re: eager vs. lazy fetching
mazz Feb 22, 2007 9:10 AM (in response to eiben)There's a lot of resources on the 'net that explain FETCH JOINs and its syntax.
Bill Burke's EJB3 book also has a chapter on JPA Queries that is good.
Google "FETCH JOIN". e.g. Here's a hibernate page that may be helpful.
http://www.hibernate.org/hib_docs/reference/en/html/queryhql.html -
4. Re: eager vs. lazy fetching
eiben Feb 22, 2007 12:57 PM (in response to eiben)OK, thanx. So I got this thingy working.
But now I have something like this, which also gives me an error, that the items are not yet fetched ...Itemgroup myItemGroup = getItemDispatcher().findItemGroup(Integer.parseInt(request.getParameter("id"))); Collection<Item> myig = myItemGroup.getItems();
and the ItemDispatcher does something like this:@Stateless public class ItemDispatcherBean implements IItemDispatcher { public Itemgroup findItemGroup(int id) { return em.find(Itemgroup.class, id); } //... }
I think that's a little bit odd ... I thought this could be fetched "on-demand" ... -
5. Re: eager vs. lazy fetching
mazz Feb 22, 2007 1:09 PM (in response to eiben)So, Itemgroup has an items relationship that is lazy loaded. Your findItemGroup is only loading in the Itemgroup entity without doing any fetch joining or eagerly loading of that relationship, hence your error.
you will need to have another method, "findItemGroupWithItems" or something like that. In that method you execute a query that does a JOIN FETCH, rather than use find(). Or you can do a find and then (still in findItemGroupWithItems method) immediately force the loading to happen by calling itemgroup.getItems().size() (this causes a second round trip to the database - not as efficient but easy to code up). -
6. Re: eager vs. lazy fetching
eiben Feb 23, 2007 9:06 AM (in response to eiben)"mazz@jboss.com" wrote:
So, Itemgroup has an items relationship that is lazy loaded. Your findItemGroup is only loading in the Itemgroup entity without doing any fetch joining or eagerly loading of that relationship, hence your error.
well, but I though when I access the items-collection the first time, the data get's loaded from the database.
you will need to have another method, "findItemGroupWithItems" or something like that. In that method you execute a query that does a JOIN FETCH, rather than use find(). Or you can do a find and then (still in findItemGroupWithItems method) immediately force the loading to happen by calling itemgroup.getItems().size() (this causes a second round trip to the database - not as efficient but easy to code up).
Do I have to make the call to the size attribute within my session-bean? It seems that it's not working as expected when I access that attribute from within my servlet.
I read in an book, that a workaround would be to use SFSB instead of SLSB, where the SFSB uses an extended persistent-context. This way I could make repeated requests to my entity as long as I don't remove the SFSB.
So I tryed something like this:Itemgroup myItemGroup = getItemDispatcherExtended().findItemGroup(Integer.parseInt(request.getParameter("id"))); Collection<Item> myig = myItemGroup.getItems(); getItemDispatcherExtended().finished();
where the ItemDispatcherExtended is a SFSB@Stateful @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public class ItemDispatcherExtendedBean implements IItemDispatcherExtended { @PersistenceContext(type = PersistenceContextType.EXTENDED) //, unitName = "business") private static EntityManager em; //... }
-
7. Re: eager vs. lazy fetching
mazz Feb 23, 2007 9:19 AM (in response to eiben)Every time you call "find" you are getting back a new attached instance initialized according to the lazy-loading properties of your entity, i.e. it will not have any relationship info that is set to LAZY. Even if you called that method from that servlet before. I believe the same behavior occurs even if you call find() again immediately after the first find() in your session bean! The semantics of the find() method seem very clear to me on this point. Every time you call it, you get a new instance initialized according to the lazy-loading properties.
Yes, obviously you need to call the size() method within your session bean because its only within there that you are still inside the scope of your entity manager and transaction. Once you return back out into your servlet layer, you are no longer within the scope of the entity manager and it cannot manage your relationships anymore (i.e. you are detached at this point). So, if you don't initialize your relationship collections prior to leaving your session bean, your servlet won't have it.
Side note: you might want to look into JBoss Seam - it provides the integration it sounds like you are looking for - that is, a seamless integration between the EJB/JPA layer and the servlet/JSF presentation layer. -
8. Re: eager vs. lazy fetching
eiben Feb 23, 2007 9:25 AM (in response to eiben)I see ... even though I'm not 100% satisfied with this answer :). As you figured, I wouold like to have a better integration into the presentation-layer.
Then again: I'm currently working on a research-project, where I want to compare two different web-application-platforms (java vs. php), so I'm writing a little app on both platforms. Using Seam would seam to me too much work ... since I'm quite new to java, and I can't spend all of my to coding java (even though, that's the most fun part to me!) -
9. Re: eager vs. lazy fetching
eiben Feb 23, 2007 12:29 PM (in response to eiben)but wait ... when I'm using SFSB and I make repeated calls, wouldn't that be like making those calls all from the same session bean? I mean ... I though using a SFSB in conjunction with an extended entity-manager should avoid that entities get detached.
-
10. Re: eager vs. lazy fetching
mazz Feb 23, 2007 12:44 PM (in response to eiben)using extended persistence contexts can work also - which is how JBoss Seam does it, I believe.
-
11. Re: eager vs. lazy fetching
eiben Feb 23, 2007 1:40 PM (in response to eiben)well ... seems not. Or I'm doing something wrong :(
That's what I read in some book, that using extened persistence and SFSB should overcome the problem of detaching entities.
hmm ... -
12. Re: eager vs. lazy fetching
amitvk Feb 4, 2008 2:17 PM (in response to eiben)Another way I found useful was using the OOP concepts to load the mappings or just the core table vlaues.
Have the main table mapped in the superclass and the mappings that you want to load sometimes in the subclass.
e.g. If the table name is Customer.
have 2 entities Customer, and CustomerWithMapping
CUstomerWithMapping extends Customer.
Define all the Customer column values in Customer base class.
Define all the lazy mappings in CustomerWithMapping class with EAGER fetch..
If you just want to get the core table data find on the Customer. If you want it with mappings call e.g. Select e from CustomerMapping where e.CustomerNumber =1.
I used the Customer class when I want to display list of customers and CustomerWithMapping when working on a specefic Customer.
Hope this helps.
P.S the only problem I found was that you cannot use em.find to get the CustomerWithMapping Object as it tries to load the superclass.
In that case use JPQL - Select e from CustomerMapping where e.CustomerNumber =1 -
13. Re: eager vs. lazy fetching
amitvk Feb 4, 2008 2:19 PM (in response to eiben)Another way I found useful was using the OOP concepts to load the mappings or just the core table vlaues.
Have the main table mapped in the superclass and the mappings that you want to load sometimes in the subclass.
e.g. If the table name is Customer.
have 2 entities Customer, and CustomerWithMapping
CUstomerWithMapping extends Customer.
Define all the Customer column values in Customer base class.
Define all the lazy mappings in CustomerWithMapping class with EAGER fetch..
If you just want to get the core table data find on the Customer. If you want it with mappings call e.g. Select e from CustomerMapping where e.CustomerNumber =1.
I used the Customer class when I want to display list of customers and CustomerWithMapping when working on a specefic Customer.
Hope this helps.
P.S the only problem I found was that you cannot use em.find to get the CustomerWithMapping Object as it tries to load the superclass.
In that case use JPQL - Select e from CustomerMapping where e.CustomerNumber =1