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
>>>>
>>>
>>>
>>
>
>