Thanks!

I changed my code to remove the key from both local and global caches (so that 
it doesn't need to know which cache was used). It now works exactly as expected 
and I can remove my work around code.

I figured I must be missing something simple.

Joe

On Aug 4, 2011, at 12:06 PM, Andrus Adamchik wrote:

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

Reply via email to