cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joseph Senecal <sene...@apple.com>
Subject Re: How to remove a single entry from cache
Date Thu, 04 Aug 2011 18:34:56 GMT
Yes, the item is committed. Stepping though the code that did the lookup I can see that it
is not going to the database at all (all SQL is being logged).

The idea is that once an item exists it is unlikely to change. But items that don't exist
are very likely to be added. So in the routine that fetches the item, it removes the entry
from the cache if nothing was fetched from the database. That way I don't need to flush the
entire cache when only this one query needs to have it's results flushed.

I did try flushing the entire cache group, but that didn't help either.

I've just managed to get a workaround working, where I keep track of the keys that didn't
fetch result and set the query to refresh in that case. That is working, though I had to switch
from a NamedQuery to a SelectQuery to be able to make that change dynamically. I left the
code to try deleting the entry in place. Here's the code I ended up with:
	private static Set<String> missingPartMap = new HashSet<String>();

	static public BOMModule moduleWithPartNum(String value, ObjectContext context) {
		if (value == null) {
			return null;
		}

		Expression expression = ExpressionFactory.matchExp(PART_NUM_PROPERTY, value);
		SelectQuery query = new SelectQuery(BOMModule.class, expression);
		query.setCacheGroups("BOMModule");
		boolean missingPart = missingPartMap.contains(value);
		query.setCacheStrategy(missingPart ? QueryCacheStrategy.SHARED_CACHE_REFRESH : QueryCacheStrategy.SHARED_CACHE);
		BOMModule part = null;
		try {
			List<BOMModule> list = fetchBOMModuleList(context, query);
			if (list.size() > 0) {
				part = list.get(0);
				if (missingPart) missingPartMap.remove(value);
			} else {
				if (!missingPart) missingPartMap.add(value);
			}
		} finally {
			if (part == null && context instanceof DataContext) {
				// No match or multiple match. Either way remove this from the cache so that we'll see
when it's fixed
				DataContext dataContext = (DataContext) context;
				String key = query.getMetaData(dataContext.getEntityResolver()).getCacheKey();
				dataContext.getQueryCache().remove(key);
				assert (dataContext.getQueryCache().get(query.getMetaData(dataContext.getEntityResolver()))
== null);
			}
		}
		return part;
	}

And here the generated fetchBOMModuleList routine from the super class: 
    @SuppressWarnings("unchecked")
    public static List<BOMModule> fetchBOMModuleList(ObjectContext context, Query query)
{
        return (List<BOMModule>) context.performQuery(query);
    }

That's just a generated helper method to hide the suppress warnings.

Sorry for having all these strange problems where things don't work for me but work for everyone
else :-/  And thanks for your prompt replies!

Joe

On Aug 4, 2011, at 11:20 AM, Andrus Adamchik wrote:

>> But when I make the same query (now that the code has created the item), I'm getting
an empty result again. 
> 
> Is that item committed? Queries are run against the DB and won't see items that haven't
been committed.
> 
> Also in general an app would invalidate cache by cache group. This way you won't need
to know the cache key of a query, and can invalidate multiple queries at once.
> 
> Andrus
> 
> 
> On Aug 4, 2011, at 5:10 AM, Joseph Senecal wrote:
> 
>> Using Cayenne 3.1M2
>> 
>> When a cached query for a single record returns no entry, I'd like to remove that
single result from the cache. Either the code will be creating the record, or it will be manually
added and I want the code to notice when it is. It looks like this should be possible using
this code:
>> 				DataContext dataContext = (DataContext) context;
>> 				String key = query.getMetaData(dataContext.getEntityResolver()).getCacheKey();
>> 				dataContext.getQueryCache().remove(key);
>> 				assert (dataContext.getQueryCache().get(query.getMetaData(dataContext.getEntityResolver()))
== null);
>> 
>> 
>> And when I run the code the assert confirms that the entry has been removed.
>> 
>> But when I make the same query (now that the code has created the item), I'm getting
an empty result again. 
>> 
>> I'd prefer not to have to flush the entire table cache whenever I create a new entry,
is this possible?
>> 
>> Joe
> 


Mime
View raw message