Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "EclipseLink/Development/JPA 2.0/cache api"
m (→20100512: [http:/bugs.eclipse.org/312503 312503]: Change IdentityMapAccessor.invalidateClass(Class, false) behaviour to also invalidate subtree) |
m (→DI 3: Eviction of a MappedSuperclass also evicts root Entity Superclass) |
||
Line 127: | Line 127: | ||
**2) How much do we invalidate when invalidating a MappedSuperclass that is not itself in the cache - but exists indirectly via implementing subclasses and because of 1) entities extended above. | **2) How much do we invalidate when invalidating a MappedSuperclass that is not itself in the cache - but exists indirectly via implementing subclasses and because of 1) entities extended above. | ||
***Currently we evict everything down from the top root Entity in the inheritance hierarchy (from E1 in [[EclipseLink/Development/JPA_2.0/cache_api#Test_Model_1|Test model 1]]) | ***Currently we evict everything down from the top root Entity in the inheritance hierarchy (from E1 in [[EclipseLink/Development/JPA_2.0/cache_api#Test_Model_1|Test model 1]]) | ||
+ | =====Decision 3:===== | ||
+ | *It was [[EclipseLink/Development/JPA_2.0/cache_api#20100512:_312503:_Change_IdentityMapAccessor.invalidateClass.28Class.2C_false.29_behaviour_to_also_invalidate_subtree|decided]] that we will implement the change in bug# [http://bugs.eclipse.org/312503 312503] and change evict(Class) behavior to evict only the subtree from '''Class''' down - and not the entire rooted tree. | ||
===Implementation=== | ===Implementation=== |
Revision as of 10:38, 12 May 2010
Contents
- 1 Cache APIs
- 1.1 Issue Summary
- 1.2 General Solution
- 1.3 Work Required
- 1.4 Implementation Details
- 1.5 Refactor 20100322
- 1.5.1 Analysis
- 1.5.1.1 Issue 1: Fix evict() to handle non-Entity classes
- 1.5.1.2 Issue 2: Refactor to get IdentityMapAccessor state through EMF reference
- 1.5.1.3 Issue 3: Refactor dependencies to use Interfaces instead of Impl subclasses
- 1.5.1.4 Issue 4: Handle no CMPPolicy case for getId()
- 1.5.1.5 Issue 5: Handle no associated descriptor for Class parameter
- 1.5.1.6 Issue 6: Add support for @MappedSuperclass descriptors
- 1.5.1.7 Issue 7: Throw an IAE for Interfaces and Embeddable classes passed to evict()
- 1.5.2 Use Cases
- 1.5.3 Design
- 1.5.4 Implementation
- 1.5.5 Testing
- 1.5.1 Analysis
- 1.6 References
- 1.7 Meetings
Cache APIs
JPA 2.0 Root | Enhancement Request
Issue Summary
In JPA 2.0 the specification has added a Cache API obtainable from an EntityManagerFactory. This simple API provides developers with rudimentary access and control of a second level cache. User's can interrogate the cache through a contains(Class, Object) API call and cause cached data to be evicted from the cache through an evict(Class, Object), evict(Class) or evictAll() API call.
See The JPA 2.0 Final Release Specification section 7.10 p.306 for details.
General Solution
Should be simple to equate evict to invalidate.
Work Required
- Develop tests
- approx 1 day
- Implement API
- approx 2 days
Implementation Details
The Cache API consists of following 4 methods
- contains(Class cls, Object primaryKey) --- checks whether the class with the specified primary key
- is contained in IdentityMap.
- evict(Class cls, Object primaryKey) --- invalidates the specified object in the IdentityMap
- evict(Class cls) --- invalidates the specified class in the IdentityMap.
- evictAll() --- Invalidates all classes in the IdentityMap.
Refactor 20100322
- See https://bugs.eclipse.org/bugs/attachment.cgi?id=165763&action=diff
- The following details describe changes to the original SVN 2896 implementation of Dec 2008 (Thank you very much Darani Y.). These modifications based on a review by Doug C. will arrive in Trunk around April 2010.
- The implementation was modified on the following dates as follows...
- 20100201: Rev# 6463 - bug# 301063 : Refactor CacheImpl to implement the EclipseLink API interface JpaCache (which implements Cache from JPA 2.0 via the new functions - clear(), clear(Class), clearQueryCache(), clearQueryCache(queryName), timeToLive(Object), isValid(Object), isValid(Class, id), print(), print(Class), printLocks(), validate(), getObject(Class, id), getObject(Object), putObject(Object), removeObject(Class), removeObject(Class, id), containsObject(Object), evictObject(Object), getId(Object)
- 20100126: Rev# 6406 - bug# 298985 : Refactor Vector usage to Id or CacheId
- 20091124: Rev# 5875 - bug# 272895 : Check invalidation during contains()
- 20090513: Rev# 4170 - bug# 275953 : Bootstrap performance and compatibility
Analysis
- Fact: Only @Entity objects are cached. @MappedSuperclass objects are not cached. @Embeddable objects are not cached directly but are cached inside their containing @Entity.
Issue 1: Fix evict() to handle non-Entity classes
- Cache.evict(Class entity) and Cache.evict(Class entity, Object key) require handling of entity Class parameters that are other than entities like MappedSuperclasses, Embeddables or non-annotated java classes.
Issue 2: Refactor to get IdentityMapAccessor state through EMF reference
- Doug: "1. Unsure if we need to hold all of this state or just hold the EMF and access
the necessary IdentityMapAccessor through this access."
- We should also get the serverSession from the EMF when required instead of caching it on the CacheImpl.
- Wherever we see... ServerSession this.serversession
- replace it with... emf.getServerSession()
Fixed/Patched in SVN Rev# NNNN
Issue 3: Refactor dependencies to use Interfaces instead of Impl subclasses
- Doug: "2. We will need to support more then just ServerSession so we need to have
impls such as this just rely on more general interfaces for the shared session such as Session or DatabaseSession interfaces." Fixed/Patched in SVN Rev# NNNN
Issue 4: Handle no CMPPolicy case for getId()
- Doug: "3. The createPKVector does not handle the case where the descriptor does not
have a CMPPolicy. This occurs when bootstrapping from native metadata."
- Avoid a possible NPE on the return from descriptor.getCMPolicy()
- createPKVector changed to createPrimaryKeyFromId to refactor out Vector usage in bug 298985
Issue 5: Handle no associated descriptor for Class parameter
- Doug: "3. continued...Also does not properly handle the case where the cls provided is not associated with
a descriptor."
- See contains(Class, Object) and contains(Object).
- The class may still be associated with a Descriptor if it is a MappedSuperclass though.
Issue 6: Add support for @MappedSuperclass descriptors
- Doug: "4. Should we support passing in MappedSuperclass or general types from the
entity inheritance tree? I believe we should."
- MappedSuperclasses do not represent real descriptors - they add functionality to concrete Entities that inherit from them - therefore they should not be evicted.
- As Gordon mentioned, we should throw an IllegalArgumentException if a Class (abstract class) representing a MappedSuperclass is passed into evict(Class) - however after further discussion between us we will evict implementing subclasses.
Fixed/Patched in SVN Rev# NNNN
Analysis 6:
- When checking for a MappedSuperclass we cannot use session.getDescriptor(class) or session.getClassDescriptor(class) because both will return the first Entity descriptor in the hierarchy if it exists. We need to check the mappedSuperclassDescriptors Map<MetadataClass, RelationalDescriptor> Map on the Project off the Session.
Issue 7: Throw an IAE for Interfaces and Embeddable classes passed to evict()
- Should we throw an IllegalArgumentException for interfaces or embeddables passed into evict(class) as well?
Use Cases
Test Model 1
- The following test model is used to validate eviction of entities at different levels and types of inheritance.
- In this case we are defining a Joined strategy on the root Entity via @Inheritance(strategy=JOINED) where the two entities have separate tables.
- Subclassing a MappedSuperclass from a root Entity is currently supported in JPA 2.0, although this is not explicitly stated...
- See p.53 section 2.11.2 and p.398 section 11.1.34 of the JPA 2.0 specification - "A class designated with the MappedSuperclass annotation can be mapped in the same way as an entity except the the mappings will apply only to its subclasses since no table exists for the mapped superclass itself". Since Entities can extend MappedSuperclasses or other Entities.
- For references see p.302 listing 10-27 of the JPA 2.0 book Pro JPA2: Mastering the Java Persistence API - where a MappedSuperclass extends an Entity.
- Class1 (non-persistable Java class)
- +--- Entity2 (abstract Entity) - cachable
- +--- MappedSuperclass3 (MappedSuperclass abstract or concrete)
- +----- Entity4a (concrete Entity) - cachable
- +--- Class5 (non-persistable Java class)
- +----- Entity4b (concrete Entity) - cachable
- +----- Entity4a (concrete Entity) - cachable
- +--- MappedSuperclass3 (MappedSuperclass abstract or concrete)
- +--- Entity2 (abstract Entity) - cachable
Design
DI 1: How to get the ID when the CMPPolicy is null
// Handle a null CMPPolicy from a MappedSuperclass Object identifier = null; if(!aDescriptor.hasCMPPolicy()) { // the following code gets the key either from the weaved _persistence_primaryKey field or using valueFromObject) if not weaved identifier = aDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, (AbstractSession)getSession()); } else { // Get identifier via EMF identifier = getEntityManagerFactory().getIdentifier(object); }
DI 2: Weaving is not being disabled for the JPA test suite
- Q)Why when weaving is turned of do I still see weaved entities in the JPA test suite?
- A)The eclipselink.annotation-model.jar has a copy of all classes unless it is excluded - the weaver for each jar causes us to weave the class because it is in two jars
<target name="package-annotation" depends="">
...
excludes="org/eclipse/persistence/testing/models/jpa/xml/**
...
org/eclipse/persistence/testing/models/jpa/metamodel/**
DI 3: Eviction of a MappedSuperclass also evicts root Entity Superclass
- Bug # 312503 directly affects the behavior or change in behavior of invalidateClass()
- This issue has 2 parts.
- 1) Do we support an inheritance heirarchy that involves Entity parents of MappedSuperclasses?
- A) Yes, we support an inheritance tree like the following - see Test Model 1 above
- Entity <-- MappedSuperclass <-- Entity
- A) Yes, we support an inheritance tree like the following - see Test Model 1 above
- 2) How much do we invalidate when invalidating a MappedSuperclass that is not itself in the cache - but exists indirectly via implementing subclasses and because of 1) entities extended above.
- Currently we evict everything down from the top root Entity in the inheritance hierarchy (from E1 in Test model 1)
- 1) Do we support an inheritance heirarchy that involves Entity parents of MappedSuperclasses?
Decision 3:
- It was decided that we will implement the change in bug# 312503 and change evict(Class) behavior to evict only the subtree from Class down - and not the entire rooted tree.
Implementation
Testing
getId() when CMPPolicy is null with weaving on
Thread [Thread-3] (Suspended) ObjectBuilder.extractPrimaryKeyFromObject(Object, AbstractSession, boolean) line: 1917 ObjectBuilder.extractPrimaryKeyFromObject(Object, AbstractSession) line: 1905 CacheImpl.getId(Object) line: 400 CacheImplJUnitTest.testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_weaving_on() line: 535
getId() when CMPPolicy is null with weaving off
Thread [Thread-3] (Suspended) ObjectBuilder.extractPrimaryKeyFromObject(Object, AbstractSession, boolean) line: 1952 ObjectBuilder.extractPrimaryKeyFromObject(Object, AbstractSession) line: 1905 CacheImpl.getId(Object) line: 400 CacheImplJUnitTest.testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_and_null_pk_with_weaving_off() line: 618
References
Meetings
20100512: 312503: Change IdentityMapAccessor.invalidateClass(Class, false) behaviour to also invalidate subtree
- After a discussion with James on the current behavior of IdentityMapAccessor.invalidateClass(Class, false)
- Good talk and decision with Gordon, Peter, Tom, Michael O'Brien in the meeting today
- see bug# 312503 http://bugs.eclipse.org/312503
- 1) - we will change the functionality of invalidateClass(Class, boolean recurse) for the case of recurse=false
- This change will now invalidate the subtree rooted at Class down
- Where previously only the single Classs was invalidated
- 2) - we will change the name of the recurse flag to something like invalidateHierachy
- no functionality change will occur when the recurse flag is true - where the entire tree to the root entity is invalidated (possibly up)
- 3) We will publish a description of the change in bug# 312503 in the 2.1 release notes for users of the recurse=false method
- 1) - we will change the functionality of invalidateClass(Class, boolean recurse) for the case of recurse=false