openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Pinaki Poddar" <ppod...@bea.com>
Subject RE: FetchGroup and FetchAttribute question
Date Tue, 04 Sep 2007 19:40:35 GMT
Teresa,

Few notes:
1. The entity classes had annotated certain fields Fetch.LAZY and test
code is verifying which fields are fetched under different fetch
configuration. Annotating a field x which otherwise would be in default
fetch group (say String FGEmployee.rating in your example) with
Fecth.LAZY will keep field x out of default fetch group. 
So if only default fetch group is active (for example, after a
resetFetchGroups() call), then em.find(FGEmployee.class, id) will fetch
a Employee but not 'rating' field. Employee.rating will only be fetched
if user code calls emp.getRating(). 

2. But if the test code does something as follows within an active
transaction:
   boolean isRatingFetched = (emp.getRating()!=null);

   then a Schrodinger's principle becomes active i.e. due to the
observation process itself, the observed gets perturbed. The result of
emp.getAddress() will *now* fetch the LAZY 'rating' field and
isRatingFetched will become true. However, em.find(FGEmployee.class, id)
may not have fetched 'rating' which is actually what the test is trying
to verify.
Some of the attached test code is impacted by this effect.
The safe way to eliminate such side-effect is to commit the transaction
and close (not clear) the entity manager *before* starting to check
which fields are fetched as a result of a find() or query result.

3. I would suggest that capture the oft-repeated code patterns in the
Test case of finding an Employee under different fetch configuration to
put in a single method like (this one ensures that the returned Employee
will not further fetch its state as a side-effect of get() calls): 

    private FGEmployee findEmployee(Object id, boolean reset,
String...fetchGroups) {
	EntityManager em = emf.createEntityManager();

      OpenJPAEntityManager oem = OpenJPAPersistence.cast(em);
    	oem.getTransaction().begin();
    	if (reset) {
    		oem.getFetchPlan().resetFetchGroups();
    		assertEquals(1,
oem.getFetchPlan().getFetchGroups().size());
    		assertEquals("[default]",
Arrays.toString(oem.getFetchPlan().getFetchGroups().toArray()));
    	}
    	if (fetchGroups!=null)
    		for (String fg:fetchGroups)
    			oem.getFetchPlan().addFetchGroup(fg);
    	FGEmployee emp = oem.find(FGEmployee.class, id);
    	oem.getTransaction().commit();
    	oem.close();
    	return emp;
    }

4. I would also suggest to use
TestCase.assertNull(emp.getRating()) or assertNotNull(emp.getRating())
wherever System.out.pritln("....") is used to verify manually.
Because without any asserts, Junit Tests think they pass!

5. Another suggestion will be *not* to mix compile-time FetchType.LAZY
and run-time fetch plans in the tests at least for initial
verifications. 
So keeping the fields without ant FecthType annotations and control what
is fetched only by run-time manipulation of fetch plans will expose the
functioning (and any possible bug) associated with fetch groups. 
In a later phase, the tests can explore how mixing compile-time
FetchType.LAZY and run-time fetch plans change the behavior.




Pinaki Poddar
972.834.2865
 

>-----Original Message-----
>From: Teresa Kan [mailto:tckan1@gmail.com] 
>Sent: Tuesday, September 04, 2007 9:26 AM
>To: dev@openjpa.apache.org
>Subject: Re: FetchGroup and FetchAttribute question
>
>Pinaki,
>I used the debugger to check that the FetchGroup was added 
>when the application explicitly added that FetchGroup. 
>I attached the testcase in this note. Please noted that I did 
>not use the Assert to verify the result because I'm not sure 
>about the outcome. I used the println to print out the result instead.
> 
>Thanks,
>Teresa 
>
> 
>On 8/31/07, Pinaki Poddar <ppoddar@bea.com> wrote: 
>
>	Hi,
>	Few comments in-line....
>	
>	What is the mechanics to cofirm if a field is loaded as 
>a result of a 
>	API call?
>	
>	Can you post a test case for us to investigate further?
>	
>	
>	Pinaki Poddar
>	972.834.2865
>	
>	
>	>-----Original Message-----
>	>From: Teresa Kan [mailto: tckan1@gmail.com 
><mailto:tckan1@gmail.com> ]
>	>Sent: Friday, August 31, 2007 11:46 AM
>	>To: dev
>	>Subject: Re: FetchGroup and FetchAttribute question
>	>
>	>In addition to previous question, I have question about the
>	>lifecycle of a FetchGroup and need some clarifications on the 
>	>expected behavior. Please verify each step result is  a
>	>correct behavior. If they are correct, then we need to
>	>document those behavior in the javadoc and openjpa manual:
>	>
>	>Use the following example, 
>	>
>	>@FetchGroups({
>	>   @FetchGroup(name="AddressFetchGroup", attributes=
>	>{@FetchAttribute(name="address")} ),
>	>   @FetchGroup(name="RatingFetchGroup", attributes= 
>	>{@FetchAttribute(name="rating")}),
>	>@FetchGroup(name="ManagerFetchGroup1A", attributes=
>	>{@FetchAttribute(name= "manager" , recursionDepth=1)} )
>	>})
>	>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;
>	>
>	>..
>	>}
>	>
>	>Test case:
>	>1.         oem.persist(employee);
>	>==> What happen to 3 fetchGroups? Are they active at this time?
>	>From the debugger, the fetchGroup was set to "default". At
>	>this time, I can't tell whether the default means those 3
>	>fetchGroups or the default w/o any custom FetchGroups? If I 
>	>did not reset the FetchGroup and  did not explicitly add the
>	>fetchGroups, both address and rating are eagerly loaded.
>	>So it implies that all 3 fetchGroup are active when the
>	>employee is persisted. 
>	
>	The custome fetch groups are not active under this 
>configuration.
>	How are you confirming that "both address and rating 
>are eagerly loaded"
>	-- looking at the SQL issued, by reflectively looking 
>into the instance? 
>	FetchGroups are not relevant during persist() operation.
>	In a clean cache, undet the 'default' configuration, 
>for a find() or
>	query, rating will be fetched and address will not.
>	
>	
>	>==> What happen if there is no LoadFetchGroup annotated on 
>	>rating? Will the AddressFetchGroup be active ?
>	>From the test result, this is true.. Then why we need to use
>	>LoadFetchGroup explicitly?
>	
>	If field a has a LoadFetchGropu X -- it means "if field 
>a is loaded also 
>	load all fields included in fecthgroup X". 
>LoadFetchGroup does not
>	control which fetch group is active.
>	
>	
>	>
>	>2.          oem.getFetchPlan().resetFetchGroups();
>	>              oem.clean(); 
>	>==> What is the expected behavior in resetFetchGroups()?
>	>According to the
>	>javadoc:
>	>Resets the set of fetch groups to the list in the 
>global configuration.
>	>What does the "global configuration" mean? The default fetch 
>	>group w/o custom fetch group? or the one that defined thru
>	>annotation? or the one in the persistence.xml file?
>	>
>	
>	'global configuration' implies the fetch groups specified in
>	persistence.xml via 'openjpa.FetchGroups' property.
>	
>	>I assume that 3 fetchGroups are not active. From the debugger,
>	>it showed the "default" which I guessed the default w/o custom
>	>fetch groups..
>	>How about the LoadFetchGroup? it seems to me that this fetch
>	>group was deactive too. Is this an expected behavior?
>	>From the test result, both address and rating are NOT  
>eargly loaded.
>	>
>	
>	LoadFetchGroup does not control which fetch group is active. 
>	
>	>
>	>3.             
>oem.getFetchPlan().addFetchGroups("RatingFetchGroup");
>	>==>  What is the expected behavior? The RatingFetchGroup is
>	>added to the fetchPlan. From the debugger, I saw both default 
>	>and RatingFetchGroup.
>	>The test result showed the rating was eagerly loaded but not
>	>the address. It seems to me that the resetFetchGroup() disable
>	>the AddressFetchGroup even though it was specified in the 
>	>rating thru LoadFetchGroup.  Is this an expected behavior?
>	>
>	>
>	>
>	>4.            FGEmployee emp = oem.find(FGEmployee.class, 1);
>	>==> What happen to the Address and Rating fields?
>	>  a) if Rating does not have the LoadFetchGroup annotation,
>	>and no resetFetchGroup call:
>	>  ===> both Address and Rating are eagerly loaded.
>	> b) if Rating has the LoadFetchGroup annotation and no 
>	>resetFetchGroup call:
>	> ===> same as a)
>	> c) Regardless of  the LoadFetchGroup, if resetFetchGroup is
>	>called and  no addFetchGroup is called:
>	> ==> both Address and Rating are not eagerly loaded. 
>	> d) If resetFetchGroup is called and addFetchGroup on
>	>RatingFetchGroup is
>	>called:
>	> ==> Address is LAZY and rating is eager.
>	> e) if resetFetchGropu is called and addFetchGroup on both 
>	>Address and Rating fetch groups:
>	> ==> both Address and Rating are eagerly loaded.
>	>
>	>5) one more question, if I defined a FetchGroup within a
>	>FetchGroup, for example, @FetchGroups({
>	>@FetchGroup(name="AggregateEmployeeFetchGroup1",
>	>                attributes= {
>	>                    @FetchAttribute(name="dept"),
>	>                    @FetchAttribute(name="address"), 
>	>                    @FetchAttribute(name="manager", 
>recursionDepth=1)
>	>                } ),
>	> @FetchGroup(name="AggregateEmployeeFetchGroup2",
>	>fetchGroups={"AggregateEmployeeFetchGroup1"} ), } ===> if I 
>	>reset the fetch group, and only add the
>	>AggregateEmployeeFetchGroup2. Nothing will happen because the
>	>AggregateEmployeeFetchGroup1 is deactivated by
>	>resetFetchGroup(). Unless I add both fetchGroup in runtime, 
>	>none of the dept, address, manager are eagerly loaded. Is this
>	>an expected behavior?
>	>
>	>Please verify the above behaviors.. I can't tell the lifecycle
>	>of the FetchGroup that associated with LoadFetchGroup and 
>	>resetFetchGroup..
>	>
>	>Thanks,
>	>Teresa
>	>
>	>
>	>
>	>
>	>
>	>
>	>
>	>On 8/30/07, Teresa Kan <tckan1@gmail.com> wrote:
>	>>
>	>> If I have a fetchAttribute manager which is included 
>in multiple
>	>> FetchGroups. For example,
>	>>
>	>> @FetchGroup(name="ManagerFetchGroup1A",
>	>>
>	>> attributes= { 
>	>> @FetchAttribute(name="manager" , recursionDepth=1)} ),
>	>>
>	>> @FetchGroup(name="ManagerFetchGroup1B",
>	>>
>	>> attributes= {
>	>> @FetchAttribute(name="manager" , recursionDepth=-1)} ), 
>	>>
>	>> @FetchGroup(name="ManagerFetchGroup2",
>	>>
>	>> attributes= {
>	>> @FetchAttribute(name="manager" , recursionDepth=2)} ),
>	>>
>	>> In my test case, I did the following: 
>	>>
>	>> oem.getFetchPlan().resetFetchGroups();  ===> reset to default
>	>>
>	>> oem.clear();
>	>>
>	>> oem.getFetchPlan().addFetchGroups(
>	>> "ManagerFetchGroup1A"); 
>	>>
>	>> I found out that openjpa will add all 3 FetchGroups back to
>	>the fetch
>	>> plan. My guess was that the manager was associated with 3
>	>FetchGroups.
>	>> The recursionDepth will be set to -1. Is this an expected 
>	>behavior? I
>	>> can't find any statement from the openjpa manual. 
>Please clarifiy!
>	>>
>	>> Thanks,
>	>>
>	>> Teresa
>	>>
>	>>
>	>>
>	>>
>	>> 
>	>>
>	>>
>	>>
>	>>
>	>>
>	>>
>	>
>	
>	Notice:  This email message, together with any 
>attachments, may contain information  of  BEA Systems,  Inc.,  
>its subsidiaries  and  affiliated entities,  that may be 
>confidential,  proprietary,  copyrighted  and/or legally 
>privileged, and is intended solely for the use of the 
>individual or entity named in this message. If you are not the 
>intended recipient, and have received this message in error, 
>please immediately return this by email and then delete it. 
>	
>
>
>

Notice:  This email message, together with any attachments, may contain information  of  BEA
Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,
 copyrighted  and/or legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient, and have received
this message in error, please immediately return this by email and then delete it.

Mime
View raw message