HiIn our application we are using LOCAL_CACHE and cache keys to refresh it, but only for a special context called 'shared' . We have overridden the CayenneContext commitChanges with following to ensure cache invalidation on every commit :
if (!isSharedContext()) {
try {
List<Class> commitedClasses = new
Vector<Class>();
for (Object o : uncommittedObjects())
if (!commitedClasses.contains(o.getClass()) && o instanceof
PersistentObject)
commitedClasses.add(o.getClass());
super.commitChanges();
for (Class<? extends PersistentObject> c :
commitedClasses) {
performGenericQuery(new RefreshQuery(new String[]
{ PersistentObject.defaultCacheKeyForEntity(c) }));
}
} catch (CayenneRuntimeException e) {
runtimeExceptionThrown(e, false);
}
} else {
logger.error("Attempt to save shared context", new
IllegalStateException("Shared context is read-only"));
}
whenever a select query is executed we are setting the cache policy
and keys
if (query instanceof SelectQuery) {
SelectQuery sq = ((SelectQuery) query);
if (isSharedContext) {
// if the query is on the shared
context then use cache
//
sq.setCachePolicy(QueryMetadata.LOCAL_CACHE);
// if the root class of the query is kind of PersistentObject
then use the cache keys
if (sq.getRoot() instanceof Class &&
PersistentObject.class.isAssignableFrom((Class<? extends
PersistentObject>) (sq.getRoot()))) {
Class<? extends PersistentObject> c = (Class<? extends
PersistentObject>) sq.getRoot();
List<String> currentCacheGroups = new
Vector<String>();
if (sq.getCacheGroups() != null)
currentCacheGroups =
Arrays.asList(sq.getCacheGroups());
String key =
PersistentObject.defaultCacheKeyForEntity(c);
if
(!currentCacheGroups.contains(key)) {
currentCacheGroups.add(key);
sq.setCacheGroups(currentCacheGroups.toArray(new String[] {}));
}
}
}
}
This works nicely, but there is one problem: the relationship query
does not return refreshed values.
An example. there are two views: One is a list of artists with painting counts, the counts are calculated using relationship (anArtist.getPaintings().size()). The second is a simple list of paintings.
1) client app 1: artists list shows:
Monet - 5
Malevich - 4
vanGogh - 3
painting list contains 12 lines
client app 2 adds a new painting for vanGogh, it lists now
Monet - 5
Malevich - 4
vanGogh - 4
painting list contains 13 lines
client app 1 lists the artists again:
Monet - 5
Malevich - 4
vanGogh - 3 <- incorrect
painting list contains 13 records, which is correct
The odd thing is also that for a given client application both lists
(artist and painting) are using the same context, so if the record is
there, why it does not show up when accessed via relationship ?
Is there something I'm doing wrong ? Is there a way to force the RelationshipQuery to refresh ?
We are using Cayenne build from sources about a month ago (svn 642725). Marcin
smime.p7s
Description: S/MIME cryptographic signature
