Example: s
I've got an object a of the class A in relationship with objects b, c and d.
If I do:
SelectQuery query = new SelectQuery(A.class);
query.addPrefetch("b").setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
query.addPrefetch("c").setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
List<?> res = context.performQuery(query);
then later:
SelectQuery query = new SelectQuery(A.class);
query.addPrefetch("d").setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
List<?> res = context.performQuery(query);
The relationships from a to b and c are invalidated (see DataRowUtils line 115).
I'm using Cayenne 3.0.2 but the behavior seems identical in versions 3.1 and 3.2M1
Is there a way to work around this issue?
My idea is to override CayenneDataObject in class A with this function:
public void writePropertyDirectly(String propName, Object val) {
if(propName.equals("b") || propName.equals("c")) {
if(val instanceof Fault && readPropertyDirectly(propName) != null) {
return;
}
}
super.writePropertyDirectly(propName, val);
}
Is that a bad idea? It seems to work.
Once loaded, I don't want to refresh b and c from the database at all.
Thanks
Actually this behavior is expected. Invalidation of to-one relationships is done eagerly on select to guarantee a fresh view of them, and on a premise that it should be easy to restore them from the memory cache when needed. So for a simple FK relationship when you call 'getB' or 'getC', you will get an object for the Fault, and you won't see a DB query.
An exception to that (an unexpected query when reading a to-one) can happen for a few reasons. The most likely one is eager garbage collection of the ObjectContext-local cache. To prevent it Cayenne 3.1 and 3.2 provide an ability to specify retain strategy set as 'cayenne.server.object_retain_strategy' property. You can try 'hard' strategy and see if there's any difference.
Your above solution is only ok if you know of all the scenarios where A is accessed and refreshed. In general it may cause hard-to-debug issues with data refreshing.