This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 272895 - JPA 2.0: CacheImpl.contains returns true for invalidated/evicted objects
Summary: JPA 2.0: CacheImpl.contains returns true for invalidated/evicted objects
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P2 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 248291
  Show dependency tree
 
Reported: 2009-04-20 10:06 EDT by Doug Clarke CLA
Modified: 2022-06-09 10:33 EDT (History)
2 users (show)

See Also:


Attachments
patch (2.79 KB, patch)
2009-11-24 15:42 EST, Chris Delahunt CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Doug Clarke CLA 2009-04-20 10:06:52 EDT
The contains method only verifies that the object is in the shared cache. It does not address objects in the cache that are invalid through expiration or explicit invalidation/eviction.

The following test fails on the assertFalse after the evict call:

   @Test
    public void evictByPK() {
        EntityManager em = getEntityManager();

        Employee emp = getExamples().minimumEmployee(em, null);

        assertNotNull(emp);
        int select =  getQuerySQLTracker(em).getTotalSQLSELECTCalls();

        Cache cache = em.getEntityManagerFactory().getCache();
        assertTrue(cache.contains(Employee.class, emp.getId()));

        em.clear();
        Employee findEmp = em.find(Employee.class, emp.getId());
        assertNotNull(findEmp);
        assertEquals(select, getQuerySQLTracker(em).getTotalSQLSELECTCalls());

        cache.evict(Employee.class, emp.getId());
        assertFalse(cache.contains(Employee.class, emp.getId()));
        
        em.clear();
        findEmp = em.find(Employee.class, emp.getId());
        assertNotNull(findEmp);
        assertTrue(getQuerySQLTracker(em).getTotalSQLSELECTCalls() > select);
    }
    
This can be fixed in the CacheImpl class by accessing the CacheKey as:

    public boolean contains(Class cls, Object primaryKey) {
        emf.verifyOpen();
        
        Vector pk =  createPKVector(cls, primaryKey);
        ClassDescriptor descriptor = this.serversession.getDescriptor(cls);
        CacheKey key = this.imap.getCacheKeyForObject(pk, cls, descriptor);
        
        return key != null && descriptor.getCacheInvalidoldationPolicy().isInvalidated(key); 
    }

Note: This requires the use of the IdentityMapAccessor (impl) and not the interface. The CacheImpl class also maintains a lot of redundant state which may want to be cleaned up as it couples the CacheImpl to the state of the EMF when it is created.
Comment 1 Doug Clarke CLA 2009-04-20 10:09:15 EDT
THe above impl of contains was missing a '!'. This one works:

    public boolean contains(Class cls, Object primaryKey) {
        emf.verifyOpen();
        
        Vector pk =  createPKVector(cls, primaryKey);
        ClassDescriptor descriptor = this.serversession.getDescriptor(cls);
        CacheKey key = this.imap.getCacheKeyForObject(pk, cls, descriptor);
        
        return key != null && !descriptor.getCacheInvalidationPolicy().isInvalidated(key); 
    }
Comment 2 Chris Delahunt CLA 2009-11-24 15:42:03 EST
Created attachment 153010 [details]
patch
Comment 3 Chris Delahunt CLA 2009-11-24 16:03:54 EST
checked in
Comment 4 Eclipse Webmaster CLA 2022-06-09 10:16:02 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:33:39 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink