cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marcin Skladaniec <mar...@ish.com.au>
Subject relationship query and cache refreshing in 3tier cayenne
Date Wed, 07 May 2008 23:25:25 GMT
Hi

In 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




Mime
View raw message