cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrus Adamchik <and...@objectstyle.org>
Subject Re: How to remove a single entry from cache
Date Thu, 04 Aug 2011 19:06:30 GMT
Local and shared cache can be implemented as separate caches, or as a single cache with different
regions. But in any event they are guaranteed to store keys in namespaces separate from each
other. Moreover per-context local caches are also separate from any other local cache.

The shared cache is attached to DataDomain:

DataContext dataContext = ..
QueryCache sharedCache = dataContext.getParentDataDomain().getQueryCache();

Andrus


On Aug 4, 2011, at 9:52 PM, Joseph Senecal wrote:

> That most certainly could be the reason. I thought there was only a single cache that
a program could have only local caches or a shared cache but not both, and that getQueryCache
returned the appropriate cache. Now the behavior makes sense.
> 
> Could you point me towards how to get access to the shared cache?
> 
> Joe
> 
> On Aug 4, 2011, at 11:46 AM, Andrus Adamchik wrote:
> 
>> I think I spotted something here... You are removing the entry from LOCAL cache of
the ObjectContext, while the query is run against SHARED cache. Could that be the reason?
>> 
>> Andrus
>> 
>> 
>> 
>> On Aug 4, 2011, at 9:34 PM, Joseph Senecal wrote:
>> 
>>> 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