[ 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)