openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joe Grassel <jgras...@mac.com>
Subject Re: [jira] Commented: (OPENJPA-370) LoadFetchGroup annotation was not recognized during the fetch1
Date Sat, 03 Nov 2007 22:17:42 GMT

On Nov 3, 2007, at 4:20 PM, Craig Russell (JIRA) wrote:

>
>    [ https://issues.apache.org/jira/browse/OPENJPA-370?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel

> #action_12540001 ]
>
> Craig Russell commented on OPENJPA-370:
> ---------------------------------------
>
> Joe Grassel commented:
>> I'm wondering what the intent of the LoadFetchGroup function was  
>> when it was designed.  The manual states:
>
>> "A field can also declare a load fetch group.  When you access a  
>> lazy loaded field for the first time, OpenJPA makes a datastore  
>> trip to fetch that field's data.  Sometimes, however, you know that  
>> whenever you access a lazy field A, you're likely to access lazy  
>> fields B and C as well.  Therefore, it would be more efficient to  
>> fetch the data for A, B, and C in the same datastore trip.  By  
>> setting A's load fetch group to the name of a fetch group  
>> containing B and C, you can tell OpenJPA to load all of these  
>> fields together when A is first accessed."
>
>> I guess I have a question about the function I'd like clarified:
>
>> What does it mean when B and C are co-fetched in the same datastore  
>> trip?  Is the data just loaded into the entitymanager's datacache  
>> and held there until a hit is made on it (when the application  
>> finally reads the entity persistable property for the first time,  
>> this would save an additional hit to the database) or is it  
>> genuinely considered eagerly fetched (entity persistable property  
>> field is populated when the entity object is constructed by the  
>> find/query operation?)
>
> It's useful to highlight when the load fetch group behavior is  
> activated: when you access a lazy loaded field for the first time.  
> This is not done during query or find, but only when the lazy loaded  
> field is accessed (from the application) and it's not already loaded.
>

So, for B and C to be loaded, the lazy-loaded field that has the load  
fetch group annotation has to be accessed while the entity is still  
managed.  When A is faulted in, it faults B and C in automatically,  
even if they are never accessed while the entity is managed.

So given the entity FGEmployee (using this since the code is already  
available as an attachment, and keeps my message shorter), which (all,  
some, or none) of the following LoadFetchGroup scenarios are valid:

Scenario A:
Starting environment:  No fetch groups other then "default" are  
active, persistence context is clear of any managed entities

1) Start a transaction
2) Find/Query FGEmployee
3) Read rating (this causes addressGroup to be faulted in, due to the  
@LoadFetchGroup on rating)
4) Commit the transaction
5) Clear the persistence context (not necessary for TS-CM PCs)
6) Read rating, since it was read while the entity was managed in step  
3, its data should be available
7) Read addressGroup, although it was not read while the entity was  
managed, it was faulted in when addressGroup was accessed in step 3,  
because of the @LoadFetchGroup, so it should be available.  Other lazy  
loaded fields, like description, dept, manager, are not available at  
this point since they were never accessed while the entity was  
managed, and since default was the only active fetch group, they would  
have observed lazy loading behavior.

Scenario B:
Starting environment: Active Fetch Groups: "default",  
"RatingFetchGroup".  Persistence context is clear of any managed  
entities

1) Start a transaction
2) Find/Query FGEmployee
3) Commit the Transaction
4) Clear the persistence context

(Note, the first four steps can be condensed to just 1 for a TS-CM PS  
if performed outside of a transaction)

5) Read rating, since it was targeted by the RatingFetchGroup, it  
should be available even though it was never accessed while the entity  
was managed.  This has been tested and proven that this is the  
observed behavior for persistable attributes identified by fetch groups.
6) Read addressGroup.  This is the rub.  Is it available?  ratings was  
loaded in because it was part of an active fetch plan.  I would expect  
that since rating was loaded, and since rating has declared that  
addressGroup should also be loaded via its @LoadFetchGroup annotation,  
then addressGroup should be available as well.

Other lazy loaded fields, like description, dept, manager, are not  
available at this point since they were never accessed while the  
entity was managed, and were never a member of any of the active fetch  
groups, they would have observed lazy loading behavior.

The documentation as it is written makes it sound like both scenarios  
are valid -- any situation where rating's data is available,  
addressGroup's data is also supposed to be available, thanks to the  
@LoadFetchGroup.  Which scenarios are valid interpretations of the  
function?  Scenario A, Scenario B, both, or neither?

> To your other point, if fields B and C are in field A's load fetch  
> group, then accessing field A makes is available in the detached  
> instance, and fields B and C are also available in the detached  
> instance as if they were accessed at the same time as field A was  
> accessed.
>
>> This makes a big difference in what an application programmer  
>> should expect.  If the former, then LoadFetchGroup is just a  
>> datastore optimization that doesn't really make B and C eagerly  
>> loaded.  It just saves a datastore trip should they ever be  
>> loaded.  That means that if the entity becomes detached, B and C  
>> are not available because they were never accessed when the entity  
>> was managed by the persistence context.
>
> Yes, this does affect the fields that are detached. If fields B and  
> C are loaded, then they are also loaded in the detached instance.  
> But I'd be careful calling this behavior eager loading. Eager  
> loading is done for fields based on the fetch plan in effect for a  
> find or query that first loads the instance into memory. The load  
> fetch group isn't considered here. The load fetch group is only  
> activated when you access a field that wasn't eagerly loaded.

So, this means that Scenario A is the only scenario where  
@LoadFetchGroup will work?  Since rating, in Scenario B, would not be  
considered a lazy loaded field because it is a member of an active  
fetch plan?

>
>
>> The latter, and the function behavior I expected, if data is  
>> acquired from the datastore hit, then I'd expect it to be available  
>> for reading from the entity object, even if the field was not  
>> access prior to becoming detached, since active fetch groups (or  
>> those referenced by a load fetch group) effectively nullify the  
>> LAZY loading setting on an affected persistable attribute.  Knowing  
>> what behavior to expect is especially important, especially in the  
>> situation where entities are acquired with a transaction-scoped  
>> persistence context when then find/query occurs outside of a  
>> transaction.  I'd expect A to be loaded because it was referenced  
>> in an active fetch group, and B and C to be loaded (and  
>> referenceable in the entity) due to the load fetch group setting.
>
> No, here's the difference between active fetch groups and load fetch  
> groups. If you want fields B and C to be loaded when the instance is  
> first accessed via find or query, then you need to include B and C  
> in one of the active fetch groups when you execute find or query. If  
> you want fields B and C to be loaded only when some lazy loaded  
> field is accessed, then put B and C into a fetch group and define  
> that fetch group as the load fetch group of the lazy loaded fields  
> that you want to trigger the fetch of fields B and C.
>
> A slightly different slant on this is that if field A is in some  
> fetch group FG1, and use of field A requires fields B and C, then  
> any fetch group that includes A (e.g. FG1) should also include B and  
> C. There's no need for a load fetch group here.
>

So, in the situation where we and both B and C to be loaded if A is  
loaded, we would either:

1) Do Scenario A
2) Have fetch groups that include A, B, and C active when the find/ 
query is performed.

If that is the case, then I think the documentation really needs to be  
updated to make that crystal clear.  Otherwise, it will be easy to  
assume (as I did) that @LoadFetchGroups will always be triggered if  
the persistable attribute annotated with it is loaded, be it  
approached in Scenario A or B.  By saying "you can tell OpenJPA to  
load all of these fields together when A is first accessed." that  
sounds like B and C will always be loaded along with A, no matter what  
the loading circumstance (A loaded by a getter method while the entity  
is managed, or A loaded in by fetch group).


>> Also, I noticed that some of the examples closed the entitymanager  
>> in order to test loadfetchgroup behavior -- what about when an  
>> entity is just detached from the persistence context, em.close() is  
>> one way to approach it, but that only works in JSE and JEE:  
>> Application Managed Persistence Contexts.  That's not going to work  
>> in Container Managed Persistence Contexts, and detachment is  
>> probably going to be frequently seen by Transaction Scoped  
>> persistence contexts, and situations where entities are serialized  
>> across the wire to distinct application components (say, to an  
>> application client, a web service, or via RMIIIOP to a remote  
>> application server's ejb/web container.)  I would expect that data  
>> to be available due to the fetchgroup/loadfetchgroup configuration.
>
> The test cases use em.clear() or em.close() to detach the instances,  
> but any operation that detaches instances, including serialization,  
> should exhibit the behavior.
>
>> This includes both non-relational and relational lazy-loaded fields.
>
> I don't understand this comment. Are you referring to relationship  
> fields?

Yes, making sure that both attributes that make sense to be lazy  
loaded (Strings, blobs, etc.) and relationships (any, although the  
collection based relationships are lazy by default) are included under  
consideration here.

>
>
>
>> LoadFetchGroup annotation was not recognized during the fetch1
>> --------------------------------------------------------------
>>
>>                Key: OPENJPA-370
>>                URL: https://issues.apache.org/jira/browse/OPENJPA-370
>>            Project: OpenJPA
>>         Issue Type: Bug
>>         Components: kernel
>>   Affects Versions: 1.0.1, 1.0.2, 1.1.0
>>           Reporter: Teresa Kan
>>           Assignee: Teresa Kan
>>            Fix For: 1.0.2, 1.1.0
>>
>>        Attachments: OPENJPA_370_2.patch, smime.p7s,  
>> TestFetchGroup.zip, TestJIRA370.zip
>>
>>
>> Employee class has a LoadFetchGroup annotation defined on the  
>> Rating field, when getRating was called, the address should be  
>> returned also. However, openjpa did not handle the LoadFetchGroup  
>> correctly, therefore, address was not eargly fetched.
>> public class FGEmployee{
>>    @Id
>>    private int id;
>>
>>    @OneToOne(fetch=FetchType.LAZY)
>>    private FGAddress address;
>>
>>    @Basic(fetch=FetchType.LAZY)
>>    @LoadFetchGroup("AddressFetchGroup")
>>    private String rating;
>>
>>    @ManyToOne(fetch=FetchType.LAZY)
>>    private FGManager manager;
>> ..
>> }
>
> -- 
> This message is automatically generated by JIRA.
> -
> You can reply to this email to add a comment to the issue online.
>


Mime
View raw message