[ 
https://issues.apache.org/jira/browse/CAY-2877?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrus Adamchik updated CAY-2877:
---------------------------------
    Description: 
Consider a chain of to-one relationships: A -> B -> C

{noformat}
// Run a query on B, prefetching C
List<B> b = ObjectSelect.query(B.class).prefetch(B.C.joint()).select(context);
assertFalse(b.get(0).readPropertyDirectly("c") instanceof Fault);


// Run a query on A, prefetching B
A a =  ObjectSelect.query(A.class).prefetch(A.B.joint()).selectOne(context);
assertFalse(b.get(0).readPropertyDirectly("c")  instanceof Fault); // <-- This 
fails
{noformat}

So a somewhat independent query run in the same context can wipe out our 
carefully crafted prefetches in the original query, resulting in massive 
faulting when you go back and process b's in a loop.

The original idea of blindly invalidating all relationships of a prefetched 
object is based on the prefetch contract - all objects in the tree must be 
refreshed from the DB. So we are not allowed to keep a stale relationship from 
B to C in the second query (e.g. it may have changed from C1 to C2 between the 
two queries via an external process). However, we should be smarter, and 
preserve at least some relationships, specifically when the fresh B snapshot 
has an FK that matches its previous value. So while C itself can become stale, 
"B.c" is still pointing to the right C ID. Of course, only works for 
relationships that have an FK that has all the target PK columns.

The current behavior is very frustrating in apps that are not using query-level 
cache.

  was:
Consider a chain of to-one relationships: A -> B -> C

{noformat}
// Run a query on B, prefetching C
List<B> b = ObjectSelect.query(B.class).prefetch(B.C.joint()).select(context);
assertFalse(b.get(0).readPropertyDirectly("c") instanceof Fault);


// Run a query on A, prefetching B
A a =  ObjectSelect.query(A.class).prefetch(A.B.joint()).selectOne(context);
assertFalse(b.get(0).readPropertyDirectly("c")  instanceof Fault); // <-- This 
fails
{noformat}

So a somewhat independent query run in the same context can wipe out our 
carefully crafted prefetches in the original query, resulting in massive 
faulting when you go back and process b's in a loop.

The original idea of blindly invalidating all relationships of a prefetched 
object is based on the prefetch contract - all objects in the tree must be 
refreshed from the DB. So we are not allowed to keep a stale relationship from 
B to C in the second query (e.g. it may have changed from C1 to C2 between the 
two queries via an external process). However, we should be smarter, and 
preserve at least some relationships, specifically when the fresh B snapshot 
has an FK that matches its previous value. So while C itself can become stale, 
"B.c" is still pointing to the right C ID. Of course, only works for 
relationships that have an FK that has all the target PK columns.  


> Don't reset unchanged to-1 relationships of prefetched objects
> --------------------------------------------------------------
>
>                 Key: CAY-2877
>                 URL: https://issues.apache.org/jira/browse/CAY-2877
>             Project: Cayenne
>          Issue Type: Improvement
>            Reporter: Andrus Adamchik
>            Priority: Major
>
> Consider a chain of to-one relationships: A -> B -> C
> {noformat}
> // Run a query on B, prefetching C
> List<B> b = ObjectSelect.query(B.class).prefetch(B.C.joint()).select(context);
> assertFalse(b.get(0).readPropertyDirectly("c") instanceof Fault);
> // Run a query on A, prefetching B
> A a =  ObjectSelect.query(A.class).prefetch(A.B.joint()).selectOne(context);
> assertFalse(b.get(0).readPropertyDirectly("c")  instanceof Fault); // <-- 
> This fails
> {noformat}
> So a somewhat independent query run in the same context can wipe out our 
> carefully crafted prefetches in the original query, resulting in massive 
> faulting when you go back and process b's in a loop.
> The original idea of blindly invalidating all relationships of a prefetched 
> object is based on the prefetch contract - all objects in the tree must be 
> refreshed from the DB. So we are not allowed to keep a stale relationship 
> from B to C in the second query (e.g. it may have changed from C1 to C2 
> between the two queries via an external process). However, we should be 
> smarter, and preserve at least some relationships, specifically when the 
> fresh B snapshot has an FK that matches its previous value. So while C itself 
> can become stale, "B.c" is still pointing to the right C ID. Of course, only 
> works for relationships that have an FK that has all the target PK columns.
> The current behavior is very frustrating in apps that are not using 
> query-level cache.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to