relationship query and cache refreshing in 3tier cayenne

From: Marcin Skladaniec (marci..sh.com.au)
Date: Wed May 07 2008 - 19:25:25 EDT

  • Next message: Borut Bolčina: "MySQL engine = NDBCLUSTER"

    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





    This archive was generated by hypermail 2.0.0 : Wed May 07 2008 - 19:26:05 EDT