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