Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 157786 Details for
Bug 298985
Improve general performance and concurrency
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
adds jpcache extensions
2010-02-01-query-cache-jpacache.patch (text/plain), 100.90 KB, created by
James Sutherland
on 2010-02-01 10:11:04 EST
(
hide
)
Description:
adds jpcache extensions
Filename:
MIME Type:
Creator:
James Sutherland
Created:
2010-02-01 10:11:04 EST
Size:
100.90 KB
patch
obsolete
>Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/config/QueryHints.java (working copy) >@@ -116,7 +116,7 @@ > * <p>Configures a randomization on the expiry invalidation time. > * This can be used to avoid bottlenecks from the cached values expiring at the same time. > * By default expiry is not randomized. >- * Valid values are number of milliseconds, Integer or Strings that can be parsed to int values. >+ * Valid values are "true" and "false", false is the default. > * @see org.eclipse.persistence.descriptors.invalidation.TimeToLiveCacheInvalidationPolicy#setInvalidationRandomized(boolean) > */ > public static final String QUERY_RESULTS_CACHE_RANDOMIZE_EXPIRY = "eclipselink.query-results-cache.randomize-expiry"; >@@ -126,7 +126,7 @@ > * <p>Configures null results to not be cached. > * This can be used to use the query cache as a secondary key index, and allow inserts of new objects. > * By default null results are cached. >- * Valid values are number of milliseconds, Integer or Strings that can be parsed to int values. >+ * Valid values are "true" and "false", false is the default. > * @see org.eclipse.persistence.queries.QueryResultsCachePolicy#setIsNullIgnored(boolean) > */ > public static final String QUERY_RESULTS_CACHE_IGNORE_NULL = "eclipselink.query-results-cache.ignore-null"; >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/ClassDescriptor.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/ClassDescriptor.java (revision 6420) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/ClassDescriptor.java (working copy) >@@ -2619,18 +2619,17 @@ > Vector mappings = getMappings(); > Object[] mappingsArray = new Object[mappings.size()]; > for (int index = 0; index < mappings.size(); index++) { >- mappingsArray[index] = mappings.elementAt(index); >+ mappingsArray[index] = mappings.get(index); > } > Arrays.sort(mappingsArray, new MappingCompare()); > mappings = NonSynchronizedVector.newInstance(mappingsArray.length); > for (int index = 0; index < mappingsArray.length; index++) { >- mappings.addElement(mappingsArray[index]); >+ mappings.add(mappingsArray[index]); > } > setMappings(mappings); > } > >- for (Enumeration mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) { >- DatabaseMapping mapping = (DatabaseMapping)mappingsEnum.nextElement(); >+ for (DatabaseMapping mapping : getMappings()) { > validateMappingType(mapping); > mapping.initialize(session); > if (mapping.isLockableMapping()){ >@@ -2650,14 +2649,14 @@ > > // JPA 2.0 Derived identities - build a map of derived id mappings. > if (mapping.derivesId()) { >- derivesIdMappings.put(mapping.getAttributeName(), mapping); >+ this.derivesIdMappings.put(mapping.getAttributeName(), mapping); > } > > // Add all the fields in the mapping to myself. > Helper.addAllUniqueToVector(getFields(), mapping.getFields()); > } > >- if(hasMappingsPostCalculateChangesOnDeleted()) { >+ if (hasMappingsPostCalculateChangesOnDeleted()) { > session.getProject().setHasMappingsPostCalculateChangesOnDeleted(true); > } > >@@ -2682,15 +2681,13 @@ > if (hasInheritance()) { > getInheritancePolicy().initialize(session); > if (getInheritancePolicy().isChildDescriptor()) { >- for (Iterator iterator = getInheritancePolicy().getParentDescriptor().getMappings().iterator(); >- iterator.hasNext();) { >- DatabaseMapping mapping = (DatabaseMapping)iterator.next(); >+ for (DatabaseMapping mapping : getInheritancePolicy().getParentDescriptor().getMappings()) { > if (mapping.isAggregateObjectMapping() || ((mapping.isForeignReferenceMapping() && (!mapping.isDirectCollectionMapping())) && (!((ForeignReferenceMapping)mapping).usesIndirection()))) { > getLockableMappings().add(mapping);// add those mappings from the parent. > } > // JPA 2.0 Derived identities - build a map of derived id mappings. > if (mapping.derivesId()) { >- derivesIdMappings.put(mapping.getAttributeName(), mapping); >+ this.derivesIdMappings.put(mapping.getAttributeName(), mapping); > } > } > } >@@ -2705,12 +2702,12 @@ > Vector mappings = getMappings(); > Object[] mappingsArray = new Object[mappings.size()]; > for (int index = 0; index < mappings.size(); index++) { >- mappingsArray[index] = mappings.elementAt(index); >+ mappingsArray[index] = mappings.get(index); > } > Arrays.sort(mappingsArray, new MappingCompare()); > mappings = NonSynchronizedVector.newInstance(mappingsArray.length); > for (int index = 0; index < mappingsArray.length; index++) { >- mappings.addElement(mappingsArray[index]); >+ mappings.add(mappingsArray[index]); > } > setMappings(mappings); > } >@@ -3238,7 +3235,7 @@ > field.setIndex(index); > } > // Set cache key type. >- if (getCacheKeyType() == null) { >+ if (getCacheKeyType() == null || (getCacheKeyType() == CacheKeyType.AUTO)) { > if ((getPrimaryKeyFields().size() > 1) || getObjectBuilder().isXMLObjectBuilder()) { > setCacheKeyType(CacheKeyType.CACHE_ID); > } else if (getPrimaryKeyFields().size() == 1) { >@@ -3251,6 +3248,8 @@ > } else { > setCacheKeyType(CacheKeyType.CACHE_ID); > } >+ } else if ((getCacheKeyType() == CacheKeyType.ID_VALUE) && (getPrimaryKeyFields().size() > 1)) { >+ session.getIntegrityChecker().handleError(DescriptorException.cannotUseIdValueForCompositeId(this)); > } > getObjectBuilder().postInitialize(session); > >@@ -5255,8 +5254,8 @@ > */ > protected void validateAfterInitialization(AbstractSession session) { > selfValidationAfterInitialization(session); >- for (Enumeration mappings = getMappings().elements(); mappings.hasMoreElements();) { >- ((DatabaseMapping)mappings.nextElement()).validateAfterInitialization(session); >+ for (DatabaseMapping mapping : getMappings()) { >+ mapping.validateAfterInitialization(session); > } > } > >@@ -5266,8 +5265,8 @@ > */ > protected void validateBeforeInitialization(AbstractSession session) { > selfValidationBeforeInitialization(session); >- for (Enumeration mappings = getMappings().elements(); mappings.hasMoreElements();) { >- ((DatabaseMapping)mappings.nextElement()).validateBeforeInitialization(session); >+ for (DatabaseMapping mapping : getMappings()) { >+ mapping.validateBeforeInitialization(session); > } > } > >@@ -5276,17 +5275,12 @@ > * Check that the qualifier on the table names are properly set. > */ > protected void verifyTableQualifiers(Platform platform) { >- DatabaseTable table; >- Enumeration tableEnumeration; > String tableQualifier = platform.getTableQualifier(); >- > if (tableQualifier.length() == 0) { > return; > } > >- tableEnumeration = getTables().elements(); >- while (tableEnumeration.hasMoreElements()) { >- table = (DatabaseTable)tableEnumeration.nextElement(); >+ for (DatabaseTable table : getTables()) { > if (table.getTableQualifier().length() == 0) { > table.setTableQualifier(tableQualifier); > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/CMPPolicy.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/CMPPolicy.java (revision 6420) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/descriptors/CMPPolicy.java (working copy) >@@ -354,14 +354,14 @@ > > /** > * INTERNAL: >- * Create an instance of the composite primary key class for the key object. >+ * Create an instance of the Id class or value from the object. > */ >- public Object createPrimaryKeyInstance(Object key, AbstractSession session) { >+ public Object createPrimaryKeyInstance(Object object, AbstractSession session) { > KeyElementAccessor[] pkElementArray = this.getKeyClassFields(getPKClass()); > ObjectBuilder builder = getDescriptor().getObjectBuilder(); > if (pkElementArray.length == 1 && pkElementArray[0] instanceof KeyIsElementAccessor){ > DatabaseMapping mapping = builder.getMappingForAttributeName(pkElementArray[0].getAttributeName()); >- Object fieldValue = mapping.getRealAttributeValueFromObject(key, session); >+ Object fieldValue = mapping.getRealAttributeValueFromObject(object, session); > if (mapping.isObjectReferenceMapping()){ > fieldValue = mapping.getReferenceDescriptor().getCMPPolicy().createPrimaryKeyInstance(fieldValue, session); > } >@@ -371,7 +371,7 @@ > Object keyInstance = getPKClassInstance(); > Set<ObjectReferenceMapping> usedObjectReferenceMappings = new HashSet<ObjectReferenceMapping>(); > for (int index = 0; index < pkElementArray.length; index++) { >- Object keyObj = key; >+ Object keyObj = object; > KeyElementAccessor accessor = pkElementArray[index]; > DatabaseField field = accessor.getDatabaseField(); > DatabaseMapping mapping = builder.getMappingForField(field); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/exceptions/DescriptorException.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/exceptions/DescriptorException.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/exceptions/DescriptorException.java (working copy) >@@ -230,6 +230,7 @@ > public final static int MULTIPLE_TARGET_FOREIGN_KEY_TABLES = 213; > public final static int ONE_TO_ONE_MAPPING_CONFLICT = 214; > public final static int NO_RELATION_TABLE_MECHANISM = 215; >+ public final static int CANNOT_USE_ID_VALUE_FOR_COMPOSITE_ID = 216; > > /** > * INTERNAL: >@@ -1993,11 +1994,20 @@ > } > > public static DescriptorException noRelationTableMechanism(DatabaseMapping mapping) { >- Object[] args = { }; >+ Object[] args = { mapping }; > > DescriptorException descriptorException = new DescriptorException(ExceptionMessageGenerator.buildMessage(DescriptorException.class, NO_RELATION_TABLE_MECHANISM, args), mapping); > descriptorException.setErrorCode(NO_RELATION_TABLE_MECHANISM); > return descriptorException; > } > >+ >+ public static DescriptorException cannotUseIdValueForCompositeId(ClassDescriptor descriptor) { >+ Object[] args = { }; >+ >+ DescriptorException descriptorException = new DescriptorException(ExceptionMessageGenerator.buildMessage(DescriptorException.class, CANNOT_USE_ID_VALUE_FOR_COMPOSITE_ID, args), descriptor); >+ descriptorException.setErrorCode(CANNOT_USE_ID_VALUE_FOR_COMPOSITE_ID); >+ return descriptorException; >+ } >+ > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/exceptions/i18n/DescriptorExceptionResource.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/exceptions/i18n/DescriptorExceptionResource.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/exceptions/i18n/DescriptorExceptionResource.java (working copy) >@@ -224,6 +224,7 @@ > { "213", "{0} requires all target foreign key fields to belong to the same table, but several were found: {1}." }, > { "214", "{0} specifies relation table, that is not compatible with addForeignKey(Name) method, or use addSourceRelationKeyField(Name) and addTargetRelationKeyFieldName methods instead."}, > { "215", "{0} must have non-null RelationTableMechanism."}, >+ { "216", "CacheKeyType cannot be ID_VALUE for a composite primary key.."}, > > }; > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/descriptors/ObjectBuilder.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/descriptors/ObjectBuilder.java (revision 6420) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/descriptors/ObjectBuilder.java (working copy) >@@ -570,10 +570,11 @@ > CacheKey unitOfWorkCacheKey = unitOfWork.getIdentityMapAccessorInstance().acquireLock(primaryKey, concreteDescriptor.getJavaClass(), concreteDescriptor); > Object clone = unitOfWorkCacheKey.getObject(); > boolean found = clone != null; >- Object original = null; >+ Object original = null; > try { > // Only check parent cache if not in unit of work, or if a refresh is required. > if (!found || query.shouldRefreshIdentityMapResult() >+ || query.shouldCacheQueryResults() // Need to build original to cache it. > || query.shouldRetrieveBypassCache() > || (concreteDescriptor.hasFetchGroupManager() && concreteDescriptor.getFetchGroupManager().isPartialObject(clone))) { > // This is normal case when we are not in transaction. >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/IdentityMapManager.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/IdentityMapManager.java (revision 6406) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/identitymaps/IdentityMapManager.java (working copy) >@@ -927,7 +927,7 @@ > * values of the parameters to the query so different parameters will have > * different cached results. > */ >- public Object getQueryResult(ReadQuery query, Vector parameters, boolean shouldCheckExpiry) { >+ public Object getQueryResult(ReadQuery query, List parameters, boolean shouldCheckExpiry) { > if (query.getQueryResultsCachePolicy() == null) { > return null; > } >@@ -1226,7 +1226,12 @@ > * Query results are cached based on the parameter values provided to the query > * different parameter values access different caches. > */ >- public void putQueryResult(ReadQuery query, Vector parameters, Object results) { >+ public void putQueryResult(ReadQuery query, List parameters, Object results) { >+ if ((results == null) || (results == InvalidObject.instance())) { >+ if (query.getQueryResultsCachePolicy().isNullIgnored()) { >+ return; >+ } >+ } > // PERF: use query name, unless no name. > Object queryKey = query.getName(); > if ((queryKey == null) || ((String)queryKey).length() == 0) { >@@ -1257,9 +1262,6 @@ > } > // Bug 6138532 - store InvalidObject for "no results", do not store null > if (results == null) { >- if (query.getQueryResultsCachePolicy().isNullIgnored()) { >- return; >- } > results = InvalidObject.instance(); > } > map.put(lookupParameters, results, null, queryTime); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IdentityMapAccessor.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IdentityMapAccessor.java (revision 6406) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IdentityMapAccessor.java (working copy) >@@ -511,7 +511,7 @@ > if (descriptor == null) { > throw ValidationException.missingDescriptor(theClass.toString()); > } >- return this.getIdentityMap(descriptor); >+ return getIdentityMap(descriptor); > } > > /** >@@ -519,16 +519,24 @@ > * Get the identity map for the given class from the IdentityMapManager > */ > public IdentityMap getIdentityMap(ClassDescriptor descriptor) { >- return getIdentityMapManager().getIdentityMap(descriptor); >+ return getIdentityMap(descriptor, false); > } > > /** > * INTERNAL: >+ * Get the identity map for the given class from the IdentityMapManager >+ */ >+ public IdentityMap getIdentityMap(ClassDescriptor descriptor, boolean returnNullIfMissing) { >+ return getIdentityMapManager().getIdentityMap(descriptor, returnNullIfMissing); >+ } >+ >+ /** >+ * INTERNAL: > * Get the cached results associated with a query. Results are cached by the > * values of the parameters to the query so different parameters will have > * different cached results. > */ >- public Object getQueryResult(ReadQuery query, Vector parameters, boolean checkExpiry) { >+ public Object getQueryResult(ReadQuery query, List parameters, boolean checkExpiry) { > return getIdentityMapManager().getQueryResult(query, parameters, checkExpiry); > } > >@@ -1003,7 +1011,7 @@ > * Query results are cached based on the parameter values provided to the query > * different parameter values access different caches. > */ >- public void putQueryResult(ReadQuery query, Vector parameters, Object results) { >+ public void putQueryResult(ReadQuery query, List parameters, Object results) { > getIdentityMapManager().putQueryResult(query, parameters, results); > } > >@@ -1131,9 +1139,11 @@ > Iterator descriptors = getSession().getDescriptors().values().iterator(); > while (descriptors.hasNext()) { > ClassDescriptor descriptor = (ClassDescriptor)descriptors.next(); >- for (Enumeration mapEnum = getIdentityMap(descriptor).elements(); >- mapEnum.hasMoreElements();) { >- iterator.startIterationOn(mapEnum.nextElement()); >+ IdentityMap cache = getIdentityMap(descriptor, true); >+ if (cache != null) { >+ for (Enumeration mapEnum = cache.elements(); mapEnum.hasMoreElements();) { >+ iterator.startIterationOn(mapEnum.nextElement()); >+ } > } > } > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IsolatedClientSessionIdentityMapAccessor.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IsolatedClientSessionIdentityMapAccessor.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/IsolatedClientSessionIdentityMapAccessor.java (working copy) >@@ -289,11 +289,11 @@ > * Get the identity map for the given class from the IdentityMapManager > */ > @Override >- public IdentityMap getIdentityMap(ClassDescriptor descriptor) { >+ public IdentityMap getIdentityMap(ClassDescriptor descriptor, boolean returnNullIfMissing) { > if (descriptor.isIsolated()) { >- return getIdentityMapManager().getIdentityMap(descriptor); >+ return getIdentityMapManager().getIdentityMap(descriptor, returnNullIfMissing); > } else { >- return ((IsolatedClientSession)session).getParent().getIdentityMapAccessorInstance().getIdentityMap(descriptor); >+ return ((IsolatedClientSession)session).getParent().getIdentityMapAccessorInstance().getIdentityMap(descriptor, returnNullIfMissing); > } > } > >@@ -304,7 +304,7 @@ > * different cached results. > */ > @Override >- public Object getQueryResult(ReadQuery query, Vector parameters, boolean checkExpiry) { >+ public Object getQueryResult(ReadQuery query, List parameters, boolean checkExpiry) { > if (((IsolatedClientSession)session).isIsolatedQuery(query)) { > return getIdentityMapManager().getQueryResult(query, parameters, checkExpiry); > } else { >@@ -412,7 +412,7 @@ > * different parameter values access different caches. > */ > @Override >- public void putQueryResult(ReadQuery query, Vector parameters, Object results) { >+ public void putQueryResult(ReadQuery query, List parameters, Object results) { > if (((IsolatedClientSession)session).isIsolatedQuery(query)) { > getIdentityMapManager().putQueryResult(query, parameters, results); > } else { >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkIdentityMapAccessor.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkIdentityMapAccessor.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkIdentityMapAccessor.java (working copy) >@@ -190,7 +190,7 @@ > * results are only cached in the parent session for UnitOfWorks > */ > @Override >- public Object getQueryResult(ReadQuery query, Vector parameters, boolean checkExpiry) { >+ public Object getQueryResult(ReadQuery query, List parameters, boolean checkExpiry) { > return ((UnitOfWorkImpl)this.session).getParent().getIdentityMapAccessorInstance().getQueryResult(query, parameters, checkExpiry); > } > >@@ -203,7 +203,7 @@ > * Results are only cached in the parent session for UnitOfWorks > */ > @Override >- public void putQueryResult(ReadQuery query, Vector parameters, Object results) { >+ public void putQueryResult(ReadQuery query, List parameters, Object results) { > ((UnitOfWorkImpl)this.session).getParent().getIdentityMapAccessorInstance().putQueryResult(query, parameters, results); > } > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DataReadQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DataReadQuery.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/DataReadQuery.java (working copy) >@@ -120,7 +120,7 @@ > Object results = getQueryResults(session, row, true); > // Bug6138532 - if results are "cached no results", return null immediately > if (results == InvalidObject.instance) { >- return null; >+ return getContainerPolicy().containerInstance(0); > } > if (results != null) { > return results; >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java (revision 6406) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ObjectLevelReadQuery.java (working copy) >@@ -105,12 +105,6 @@ > */ > protected int inMemoryQueryIndirectionPolicy; > >- /** >- * Used to set the read time on objects that use this query. >- * Should be set to the time the query returned from the database. >- */ >- protected long executionTime = 0; >- > /** Allow for a query level fetch group to be set. */ > protected FetchGroup fetchGroup; > >@@ -2118,14 +2112,6 @@ > } > > /** >- * INTERNAL: >- * Set the the time this query went to the database. >- */ >- public void setExecutionTime(long executionTime) { >- this.executionTime = executionTime; >- } >- >- /** > * PUBLIC: > * Set the example object of the query to be the newExampleObject. > * The example object is used for Query By Example. >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadAllQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadAllQuery.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadAllQuery.java (working copy) >@@ -444,18 +444,18 @@ > protected Object executeObjectLevelReadQuery() throws DatabaseException { > Object result = null; > >- if (getContainerPolicy().overridesRead()) { >- return getContainerPolicy().execute(); >+ if (this.containerPolicy.overridesRead()) { >+ return this.containerPolicy.execute(); > } > > if (this.descriptor.isDescriptorForInterface()) { > Object returnValue = this.descriptor.getInterfacePolicy().selectAllObjectsUsingMultipleTableSubclassRead(this); >- setExecutionTime(System.currentTimeMillis()); >+ this.executionTime = System.currentTimeMillis(); > return returnValue; > } > > List rows = getQueryMechanism().selectAllRows(); >- setExecutionTime(System.currentTimeMillis()); >+ this.executionTime = System.currentTimeMillis(); > > // If using 1-m joins, must set all rows. > if (hasJoining() && this.joinedAttributeManager.isToManyJoin()) { >@@ -465,7 +465,7 @@ > if (this.session.isUnitOfWork()) { > result = registerResultInUnitOfWork(rows, (UnitOfWorkImpl)this.session, this.translationRow, true);// > } else { >- result = getContainerPolicy().containerInstance(rows.size()); >+ result = this.containerPolicy.containerInstance(rows.size()); > this.descriptor.getObjectBuilder().buildObjectsInto(this, rows, result); > } > >@@ -473,13 +473,18 @@ > ComplexQueryResult complexResult = new ComplexQueryResult(); > complexResult.setResult(result); > complexResult.setData(rows); >- return complexResult; >+ result = complexResult; > } > > // Add the other (already registered) results and return them. >- if (getDescriptor().hasTablePerClassPolicy()) { >- result = containerPolicy.concatenateContainers(result, getDescriptor().getTablePerClassPolicy().selectAllObjectsUsingMultipleTableSubclassRead(this)); >+ if (this.descriptor.hasTablePerClassPolicy()) { >+ result = this.containerPolicy.concatenateContainers(result, this.descriptor.getTablePerClassPolicy().selectAllObjectsUsingMultipleTableSubclassRead(this)); > } >+ >+ // If the results were empty, then ensure they get cached still. >+ if (shouldCacheQueryResults() && this.containerPolicy.isEmpty(result)) { >+ this.temporaryCachedQueryResults = InvalidObject.instance(); >+ } > > return result; > } >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadObjectQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadObjectQuery.java (revision 6406) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadObjectQuery.java (working copy) >@@ -156,12 +156,16 @@ > * It will cause the original to be cached in the query results if the query > * is set to do so. > */ >- public void cacheResult(Object unwrappedOriginal) { >- Object cachableObject = unwrappedOriginal; >- if (shouldUseWrapperPolicy()){ >- cachableObject = getSession().wrapObject(unwrappedOriginal); >+ public void cacheResult(Object object) { >+ Object cachableObject = object; >+ if (object == null) { >+ this.temporaryCachedQueryResults = InvalidObject.instance(); >+ } else { >+ if (this.shouldUseWrapperPolicy) { >+ cachableObject = this.session.wrapObject(object); >+ } >+ this.temporaryCachedQueryResults = cachableObject; > } >- setTemporaryCachedQueryResults(cachableObject); > } > > >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadQuery.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadQuery.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/queries/ReadQuery.java (working copy) >@@ -12,6 +12,7 @@ > ******************************************************************************/ > package org.eclipse.persistence.queries; > >+import java.util.List; > import java.util.Vector; > import org.eclipse.persistence.internal.helper.NonSynchronizedVector; > import org.eclipse.persistence.internal.sessions.AbstractRecord; >@@ -107,8 +108,12 @@ > */ > protected void clonedQueryExecutionComplete(DatabaseQuery query, AbstractSession session) { > if (shouldCacheQueryResults()) { >- // Cached query results must exist on the original query rather than the cloned one >- setQueryResults(((ReadQuery)query).getTemporaryCachedQueryResults(), query.getTranslationRow(), query.getSession()); >+ Object result = ((ReadQuery)query).getTemporaryCachedQueryResults(); >+ // If the temporary results were never set, then don't cache null. >+ if (result != null) { >+ // Cached query results must exist on the original query rather than the cloned one. >+ setQueryResults(result, query.getTranslationRow(), query.getSession()); >+ } > } > } > >@@ -216,10 +221,8 @@ > */ > protected Object getQueryResults(AbstractSession session, AbstractRecord row, boolean checkExpiry) { > // Check for null translation row. >- Vector arguments = null; >- if (row == null) { >- arguments = new NonSynchronizedVector(1); >- } else { >+ List arguments = null; >+ if (row != null) { > arguments = row.getValues(); > } > return session.getIdentityMapAccessorInstance().getQueryResult(this, arguments, checkExpiry); >Index: foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/IdentityMapAccessor.java >=================================================================== >--- foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/IdentityMapAccessor.java (revision 6403) >+++ foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/sessions/IdentityMapAccessor.java (working copy) >@@ -273,7 +273,7 @@ > /** > * ADVANCED: > * Returns the remaining life of the given Object. This method is associated with use of >- * TopLink's cache invalidation feature and returns the difference between the next expiry >+ * cache invalidation feature and returns the difference between the next expiry > * time of the Object and its read time. The method will return 0 for invalidated Objects. > * @param object Object under consideration > * @return long time in milliseconds >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/Employee.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/Employee.java (revision 6403) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/models/jpa/advanced/Employee.java (working copy) >@@ -115,14 +115,21 @@ > query="SELECT e FROM Employee e", > hints={ > @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE, value="true"), >- @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_TYPE, value="SOFT"), >- @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_IGNORE_NULL, value="true"), >+ @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_TYPE, value="FULL"), >+ @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_IGNORE_NULL, value="false"), > @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_RANDOMIZE_EXPIRY, value="true"), > @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_SIZE, value="200"), >- @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_EXPIRY, value="5000") >+ @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE_EXPIRY, value="50000") > } > ), > @NamedQuery( >+ name="CachedNoEmployees", >+ query="SELECT e FROM Employee e where 1 <> 1", >+ hints={ >+ @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE, value="true") >+ } >+), >+@NamedQuery( > name="CachedTimeOfDayAllEmployees", > query="SELECT e FROM Employee e", > hints={ >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/CacheImplJUnitTest.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/CacheImplJUnitTest.java (revision 6403) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/advanced/CacheImplJUnitTest.java (working copy) >@@ -17,6 +17,7 @@ > import junit.framework.TestSuite; > import org.eclipse.persistence.testing.models.jpa.advanced.*; > import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl; >+import org.eclipse.persistence.jpa.JpaCache; > import org.eclipse.persistence.testing.framework.junit.JUnitTestCase; > > /** >@@ -33,14 +34,7 @@ > super(name); > } > >- public static void setUpClass() throws Exception { >- } >- >- public static void tearDownClass() throws Exception { >- } >- > public void setUp() { >- > super.setUp(); > clearCache(); > } >@@ -55,6 +49,7 @@ > suite.addTest(new CacheImplJUnitTest("testEvictClass")); > suite.addTest(new CacheImplJUnitTest("testEvictAll")); > suite.addTest(new CacheImplJUnitTest("testEvictContains")); >+ suite.addTest(new CacheImplJUnitTest("testCacheAPI")); > > return suite; > } >@@ -79,13 +74,41 @@ > em1.persist(e1); > commitTransaction(em1); > closeEntityManager(em1); >- try { >- boolean result = getEntityManagerFactory("default1").getCache().contains(Employee.class, 101); >- assertTrue("Assertion Error",result); >- } catch (Exception e) { >- e.printStackTrace(); >- } >+ boolean result = getEntityManagerFactory("default1").getCache().contains(Employee.class, 101); >+ assertTrue("Employee not found in cache", result); > } >+ >+ /** >+ * Test cache API. >+ */ >+ public void testCacheAPI() { >+ EntityManager em = createEntityManager("default1"); >+ beginTransaction(em); >+ Employee employee = new Employee(); >+ employee.setFirstName("testCacheAPI"); >+ em.persist(employee); >+ commitTransaction(em); >+ closeEntityManager(em); >+ JpaCache cache = (JpaCache)getEntityManagerFactory("default1").getCache(); >+ assertTrue("Employee not valid in cache", cache.isValid(employee)); >+ assertTrue("Employee not valid in cache", cache.isValid(Employee.class, employee.getId())); >+ cache.timeToLive(employee); >+ assertTrue("Employee not found in cache", cache.getObject(Employee.class, employee.getId()) != null); >+ assertTrue("Employee not found in cache", cache.contains(employee)); >+ cache.evict(employee); >+ cache.putObject(employee); >+ cache.removeObject(employee); >+ cache.removeObject(Employee.class, employee.getId()); >+ cache.clear(); >+ cache.clear(Employee.class); >+ cache.clearQueryCache(); >+ cache.clearQueryCache("findAllEmployeesByIdAndFirstName"); >+ assertTrue("Employee id not correct", employee.getId().equals(cache.getId(employee))); >+ cache.print(); >+ cache.print(Employee.class); >+ cache.printLocks(); >+ cache.validate(); >+ } > > /** > * Test of evict method, of class CacheImpl. >@@ -111,8 +134,6 @@ > Employee e3 = em4.find(Employee.class, 121); > afterCache = e3.getFirstName(); > assertNotSame("Assertion Error", beforeCache, afterCache); >- } catch (Exception e) { >- e.printStackTrace(); > } finally { > closeEntityManager(em3); > closeEntityManager(em4); >@@ -141,8 +162,6 @@ > Employee e5 = em7.find(Employee.class, 131); > String actual = e5.getFirstName(); > assertNotSame("Assertion Error", expected, actual); >- } catch (Exception e) { >- e.printStackTrace(); > } finally { > closeEntityManager(em6); > closeEntityManager(em7); >@@ -180,8 +199,6 @@ > String actualDept = d2.getName(); > assertEquals("Assertion Error", expectedEmp, actualEmp); > assertEquals("Assertion Error", expectedDept, actualDept); >- } catch (Exception e) { >- e.printStackTrace(); > } finally { > closeEntityManager(em9); > } >@@ -196,7 +213,7 @@ > em.persist(emp); > commitTransaction(em); > >- try{ >+ try { > assertTrue(em.getEntityManagerFactory().getCache().contains(Employee.class, emp.getId())); > > em.clear(); >@@ -206,7 +223,7 @@ > em.getEntityManagerFactory().getCache().evict(Employee.class, emp.getId()); > assertFalse(em.getEntityManagerFactory().getCache().contains(Employee.class, emp.getId())); > } finally { >- this.closeEntityManager(em); >+ closeEntityManager(em); > } > > } >Index: jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/jpql/AdvancedQueryTestSuite.java >=================================================================== >--- jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/jpql/AdvancedQueryTestSuite.java (revision 6403) >+++ jpa/eclipselink.jpa.test/src/org/eclipse/persistence/testing/tests/jpa/jpql/AdvancedQueryTestSuite.java (working copy) >@@ -26,7 +26,6 @@ > import javax.persistence.EntityManager; > import javax.persistence.RollbackException; > >-import junit.framework.Assert; > import junit.framework.Test; > import junit.framework.TestSuite; > >@@ -39,6 +38,7 @@ > import org.eclipse.persistence.descriptors.invalidation.DailyCacheInvalidationPolicy; > import org.eclipse.persistence.descriptors.invalidation.TimeToLiveCacheInvalidationPolicy; > import org.eclipse.persistence.internal.sessions.AbstractSession; >+import org.eclipse.persistence.jpa.JpaCache; > import org.eclipse.persistence.jpa.JpaQuery; > import org.eclipse.persistence.queries.Cursor; > import org.eclipse.persistence.queries.ReadQuery; >@@ -49,6 +49,7 @@ > import org.eclipse.persistence.testing.framework.junit.JUnitTestCase; > import org.eclipse.persistence.testing.framework.QuerySQLTracker; > import org.eclipse.persistence.testing.models.jpa.advanced.Employee; >+import org.eclipse.persistence.testing.models.jpa.advanced.Address; > import org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator; > import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator; > >@@ -745,7 +746,7 @@ > if (!(readQuery.getQueryResultsCachePolicy().getCacheInvalidationPolicy() instanceof TimeToLiveCacheInvalidationPolicy)) { > fail("Query cache invalidation not set."); > } >- if (((TimeToLiveCacheInvalidationPolicy)readQuery.getQueryResultsCachePolicy().getCacheInvalidationPolicy()).getTimeToLive() != 5000) { >+ if (((TimeToLiveCacheInvalidationPolicy)readQuery.getQueryResultsCachePolicy().getCacheInvalidationPolicy()).getTimeToLive() != 50000) { > fail("Query cache invalidation time not set."); > } > >@@ -772,8 +773,37 @@ > // Query by primary key. > Query query = em.createNamedQuery("CachedAllEmployees"); > if (result.size() != query.getResultList().size()) { >+ fail("List result size is not correct on 2nd cached query."); >+ } >+ if (counter.getSqlStatements().size() > 0) { >+ fail("Query cache was not used: " + counter.getSqlStatements()); >+ } >+ ((JpaCache)getEntityManagerFactory().getCache()).clearQueryCache(); >+ // Preload uow to test query cache in uow. >+ em.createQuery("Select e from Employee e").getResultList(); >+ query.getResultList(); >+ if (result.size() != query.getResultList().size()) { >+ fail("List result size is not correct on cached query in unit of work."); >+ } >+ ((JpaCache)getEntityManagerFactory().getCache()).clearQueryCache(); >+ // Also test query cache in early transaction. >+ em.persist(new Address()); >+ em.flush(); >+ query.getResultList(); >+ if (result.size() != query.getResultList().size()) { >+ fail("List result size is not correct on cached query in transaction."); >+ } >+ // Query by primary key. >+ query = em.createNamedQuery("CachedNoEmployees"); >+ if (!query.getResultList().isEmpty()) { > fail("List result size is not correct."); > } >+ // Also test empty query cache. >+ counter.remove(); >+ counter = new QuerySQLTracker(getServerSession()); >+ if (!query.getResultList().isEmpty()) { >+ fail("List result size is not correct."); >+ } > if (counter.getSqlStatements().size() > 0) { > fail("Query cache was not used: " + counter.getSqlStatements()); > } >@@ -1310,8 +1340,6 @@ > } > > public void testLockWithSecondaryTable() { >- ServerSession session = JUnitTestCase.getServerSession(); >- > // Cannot create parallel entity managers in the server. > if (! isOnServer() && isSelectForUpateSupported()) { > EntityManager em = createEntityManager(); >@@ -1361,8 +1389,6 @@ > } > > public void testVersionChangeWithReadLock() { >- ServerSession session = JUnitTestCase.getServerSession(); >- > // It's a JPA2.0 feature. > if (! isJPA10() && isSelectForUpateNoWaitSupported()){ > Employee employee = null; >@@ -1440,8 +1466,6 @@ > } > > public void testVersionChangeWithWriteLock() { >- ServerSession session = JUnitTestCase.getServerSession(); >- > // It's a JPA2.0 feature > if (! isJPA10() && isSelectForUpateNoWaitSupported()) { > Employee employee = null; >Index: jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/CacheImpl.java >=================================================================== >--- jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/CacheImpl.java (revision 6406) >+++ jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/CacheImpl.java (working copy) >@@ -12,9 +12,9 @@ > ******************************************************************************/ > package org.eclipse.persistence.internal.jpa; > >-import javax.persistence.Cache; > import org.eclipse.persistence.descriptors.ClassDescriptor; > import org.eclipse.persistence.internal.identitymaps.CacheKey; >+import org.eclipse.persistence.jpa.JpaCache; > import org.eclipse.persistence.sessions.IdentityMapAccessor; > import org.eclipse.persistence.sessions.server.ServerSession; > >@@ -22,7 +22,7 @@ > * Implements the JPA Cache interface using the EclipseLink cache API through IdentityMapAccessor. > * @author DaraniY > */ >-public class CacheImpl implements Cache { >+public class CacheImpl implements JpaCache { > > private IdentityMapAccessor accessor; > private EntityManagerFactoryImpl emf; >@@ -34,34 +34,224 @@ > this.serversession = emf.getServerSession(); > } > >- public boolean contains(Class cls, Object primaryKey) { >+ /** >+ * Returns true if the cache contains an Object with the id and Class type, and is valid. >+ */ >+ public boolean contains(Class cls, Object id) { > this.emf.verifyOpen(); >- Object pk = createPrimaryKeyFromId(cls, primaryKey); >+ Object pk = createPrimaryKeyFromId(cls, id); > ClassDescriptor descriptor = this.serversession.getDescriptor(cls); > CacheKey key = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor)this.accessor).getCacheKeyForObject(pk, cls, descriptor); > > return (key != null) && (key.getObject() != null) && (!descriptor.getCacheInvalidationPolicy().isInvalidated(key)); > } > >- public void evict(Class cls, Object primaryKey) { >+ /** >+ * Sets an Object with the id and Class type to be invalid in the cache. >+ */ >+ public void evict(Class cls, Object id) { > this.emf.verifyOpen(); >- this.accessor.invalidateObject(createPrimaryKeyFromId(cls, primaryKey), cls); >+ this.accessor.invalidateObject(createPrimaryKeyFromId(cls, id), cls); > } > >+ /** >+ * Sets all instances of the class to be invalid. >+ */ > public void evict(Class cls) { > this.emf.verifyOpen(); > this.accessor.invalidateClass(cls); > } > >+ /** >+ * Sets all instances in the cache to be invalid. >+ */ > public void evictAll() { > this.emf.verifyOpen(); > this.accessor.invalidateAll(); > } > >- private Object createPrimaryKeyFromId(Class cls, Object primaryKey){ >- ClassDescriptor cdesc = this.serversession.getDescriptor(cls); >- CMP3Policy cmp = (CMP3Policy) (cdesc.getCMPPolicy()); >- Object pk = cmp.createPrimaryKeyFromId(primaryKey, this.serversession); >- return pk; >+ /** >+ * Return the EclipseLink cache key object from the JPA Id object. >+ */ >+ private Object createPrimaryKeyFromId(Class cls, Object id) { >+ CMP3Policy policy = (CMP3Policy)this.serversession.getDescriptor(cls).getCMPPolicy(); >+ Object primaryKey = policy.createPrimaryKeyFromId(id, this.serversession); >+ return primaryKey; > } >+ >+ /** >+ * ADVANCED: >+ * Resets the entire Object cache, and the Query cache. >+ * <p> NOTE: Be careful using this method. This method blows away both this session's and its parent's caches. >+ * This includes the server cache or any other cache. This throws away any Objects that have been read in. >+ * Extreme caution should be used before doing this because Object identity will no longer >+ * be maintained for any Objects currently read in. This should only be called >+ * if the application knows that it no longer has references to Objects held in the cache. >+ */ >+ public void clear() { >+ this.emf.verifyOpen(); >+ this.accessor.initializeAllIdentityMaps(); >+ } >+ >+ /** >+ * ADVANCED: >+ * Resets the cache for only the instances of the given Class type. >+ * For inheritance the user must make sure that they only use the root class, >+ * clearing a subclass cache is not allowed (as they share their parents cache). >+ * <p> NOTE: Caution must be used in doing this to ensure that the Objects within the cache >+ * are not referenced from other Objects of other classes or from the application. >+ */ >+ public void clear(Class cls) { >+ this.emf.verifyOpen(); >+ this.accessor.initializeIdentityMap(cls); >+ } >+ >+ /** >+ * Clear all the query caches. >+ */ >+ public void clearQueryCache() { >+ this.emf.verifyOpen(); >+ this.accessor.clearQueryCache(); >+ } >+ >+ /** >+ * Clear the named query cache associated with the query name. >+ */ >+ public void clearQueryCache(String queryName) { >+ this.emf.verifyOpen(); >+ this.accessor.clearQueryCache(queryName); >+ } >+ >+ /** >+ * Returns the remaining life of the given Object (in milliseconds). This method is associated with use of >+ * cache invalidation feature and returns the difference between the next expiry >+ * time of the Object and its read time. The method will return 0 for invalidated Objects. >+ */ >+ public long timeToLive(Object object) { >+ this.emf.verifyOpen(); >+ return this.accessor.getRemainingValidTime(object); >+ } >+ >+ /** >+ * Returns true if the Object with the same id and Class type of the >+ * the given Object is valid in the cache. >+ */ >+ public boolean isValid(Object object) { >+ this.emf.verifyOpen(); >+ return this.accessor.isValid(object); >+ } >+ >+ /** >+ * Returns true if the Object with the id and Class type is valid in the cache. >+ */ >+ public boolean isValid(Class cls, Object id) { >+ this.emf.verifyOpen(); >+ return this.accessor.isValid(createPrimaryKeyFromId(cls, id), cls); >+ } >+ >+ /** >+ * Used to print all the Objects in the cache. >+ * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level. >+ */ >+ public void print() { >+ this.emf.verifyOpen(); >+ this.accessor.printIdentityMaps(); >+ } >+ >+ /** >+ * Used to print all the Objects in the cache of the Class type. >+ * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level. >+ */ >+ public void print(Class cls) { >+ this.emf.verifyOpen(); >+ this.accessor.printIdentityMap(cls); >+ } >+ >+ /** >+ * Used to print all the currently locked cache keys in the cache. >+ * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level. >+ */ >+ public void printLocks() { >+ this.emf.verifyOpen(); >+ this.accessor.printIdentityMapLocks(); >+ } >+ >+ /** >+ * This can be used to help debugging an Object identity problem. >+ * An Object identity problem is when an Object in the cache references an >+ * Object that is not in the cache. This method will validate that all cached >+ * Objects are in a correct state. >+ */ >+ public void validate() { >+ this.emf.verifyOpen(); >+ this.accessor.validateCache(); >+ } >+ >+ /** >+ * Returns the Object from the cache map with the id >+ * and Class type. >+ */ >+ public Object getObject(Class cls, Object id) { >+ this.emf.verifyOpen(); >+ return this.accessor.getFromIdentityMap(createPrimaryKeyFromId(cls, id), cls); >+ } >+ >+ /** >+ * ADVANCED: >+ * Puts the given Object into the cache. >+ * This is a very advanced method, and caution should be used in adding objects to the cache >+ * as other objects may have relationships to previous object, or this object may have >+ * relationships to other objects. >+ */ >+ public Object putObject(Object object) { >+ this.emf.verifyOpen(); >+ return this.accessor.putInIdentityMap(object); >+ } >+ >+ /** >+ * ADVANCED: >+ * Removes the Object from the cache. >+ * <p> NOTE: Caution should be used when calling to avoid violating Object identity. >+ * The application should only call this if its known that no references to the Object exist. >+ */ >+ public Object removeObject(Object object) { >+ this.emf.verifyOpen(); >+ return this.accessor.removeFromIdentityMap(object); >+ } >+ >+ /** >+ * ADVANCED: >+ * Removes the Object with the id and Class type from the cache. >+ * <p> NOTE: Caution should be used when calling to avoid violating Object identity. >+ * The application should only call this if its known that no references to the Object exist. >+ */ >+ public Object removeObject(Class cls, Object id) { >+ this.emf.verifyOpen(); >+ return this.accessor.removeFromIdentityMap(createPrimaryKeyFromId(cls, id), cls); >+ } >+ >+ /** >+ * Returns true if the cache contains an Object with the same id and Class type of the given object. >+ */ >+ public boolean contains(Object object) { >+ return contains(object.getClass(), getId(object)); >+ } >+ >+ /** >+ * Sets the object to be invalid in the cache. >+ */ >+ public void evict(Object object) { >+ this.emf.verifyOpen(); >+ this.accessor.invalidateObject(object); >+ } >+ >+ /** >+ * Returns the object's Id. >+ */ >+ public Object getId(Object object) { >+ this.emf.verifyOpen(); >+ ClassDescriptor cdesc = this.serversession.getDescriptor(object.getClass()); >+ CMP3Policy policy = (CMP3Policy) (cdesc.getCMPPolicy()); >+ return policy.createPrimaryKeyInstance(object, this.serversession); >+ } > } >Index: jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java >=================================================================== >--- jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java (revision 6403) >+++ jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/EntityManagerFactoryImpl.java (working copy) >@@ -52,586 +52,601 @@ > * > * @author gyorke > * @since TopLink Essentials - JPA 1.0 >- * >- * 03/19/2009-2.0 Michael O'Brien >- * - 266912: JPA 2.0 Metamodel API (part of the JSR-317 EJB 3.1 Criteria API) >- */ >+ * >+ * 03/19/2009-2.0 Michael O'Brien - 266912: JPA 2.0 Metamodel API (part >+ * of the JSR-317 EJB 3.1 Criteria API) >+ */ > public class EntityManagerFactoryImpl implements EntityManagerFactory, PersistenceUnitUtil { >- /** Reference to Cache Interface. */ >- protected Cache myCache; >- /** Reference to the ServerSession for this deployment. */ >- protected volatile ServerSession serverSession; >- /** EntityManagerSetupImpl that deployed this factory. */ >- protected EntityManagerSetupImpl setupImpl; >- /** Stores if closed has been called. */ >- protected boolean isOpen = true; >- /** Persistence unit properties from create factory. */ >- protected Map properties; >+ /** Reference to Cache Interface. */ >+ protected Cache myCache; >+ /** Reference to the ServerSession for this deployment. */ >+ protected volatile ServerSession serverSession; >+ /** EntityManagerSetupImpl that deployed this factory. */ >+ protected EntityManagerSetupImpl setupImpl; >+ /** Stores if closed has been called. */ >+ protected boolean isOpen = true; >+ /** Persistence unit properties from create factory. */ >+ protected Map properties; > >- /** >- * INTERNAL: >- * The following properties passed to createEMF cached and processed on the emf directly. >- * None of these properties processed during predeploy or deploy. >+ /** >+ * INTERNAL: The following properties passed to createEMF cached and >+ * processed on the emf directly. None of these properties processed during >+ * predeploy or deploy. > **/ >- protected static final Set<String> supportedNonServerSessionProperties = PersistenceUnitProperties.getSupportedNonServerSessionProperties(); >- >- /** >- * Default join existing transaction property, allows reading through write >- * connection. >- */ >- protected boolean beginEarlyTransaction; >+ protected static final Set<String> supportedNonServerSessionProperties = PersistenceUnitProperties.getSupportedNonServerSessionProperties(); > >- /** Default property, allows flush before query to be avoided. */ >- protected FlushModeType flushMode = FlushModeType.AUTO; >+ /** >+ * Default join existing transaction property, allows reading through write >+ * connection. >+ */ >+ protected boolean beginEarlyTransaction; > >- /** Default property, allows weak unit of work references. */ >- protected ReferenceMode referenceMode = ReferenceMode.HARD; >+ /** Default property, allows flush before query to be avoided. */ >+ protected FlushModeType flushMode = FlushModeType.AUTO; > >- /** >- * Default property to avoid resuming unit of work if going to be closed on >- * commit anyway. >- */ >- protected boolean closeOnCommit; >+ /** Default property, allows weak unit of work references. */ >+ protected ReferenceMode referenceMode = ReferenceMode.HARD; > >- /** >- * Default property to avoid discover new objects in unit of work if >- * application always uses persist. >- */ >- protected boolean persistOnCommit = true; >+ /** >+ * Default property to avoid resuming unit of work if going to be closed on >+ * commit anyway. >+ */ >+ protected boolean closeOnCommit; > >- /** >- * Default FlashClearCache mode to be used. Relevant only in case call to >- * flush method followed by call to clear method. >- * >- * @see org.eclipse.persistence.config.FlushClearCache >- */ >- protected String flushClearCache = FlushClearCache.DEFAULT; >+ /** >+ * Default property to avoid discover new objects in unit of work if >+ * application always uses persist. >+ */ >+ protected boolean persistOnCommit = true; > >- /** Default to determine if does-exist should be performed on persist. */ >- protected boolean shouldValidateExistence; >- protected boolean commitWithoutPersistRules; >+ /** >+ * Default FlashClearCache mode to be used. Relevant only in case call to >+ * flush method followed by call to clear method. >+ * >+ * @see org.eclipse.persistence.config.FlushClearCache >+ */ >+ protected String flushClearCache = FlushClearCache.DEFAULT; > >- /** >- * Will return an instance of the Factory. Should only be called by >- * EclipseLink. >- * >- * @param serverSession >- */ >- public EntityManagerFactoryImpl(ServerSession serverSession) { >- this.serverSession = serverSession; >- processProperties(serverSession.getProperties()); >- } >+ /** Default to determine if does-exist should be performed on persist. */ >+ protected boolean shouldValidateExistence; >+ protected boolean commitWithoutPersistRules; > >- public EntityManagerFactoryImpl(EntityManagerSetupImpl setupImpl, Map properties) { >- this.setupImpl = setupImpl; >- this.properties = properties; >- } >+ /** >+ * Will return an instance of the Factory. Should only be called by >+ * EclipseLink. >+ * >+ * @param serverSession >+ */ >+ public EntityManagerFactoryImpl(ServerSession serverSession) { >+ this.serverSession = serverSession; >+ processProperties(serverSession.getProperties()); >+ } > >- /** >- * INTERNAL: Returns the ServerSession that the Factory will be using and >- * initializes it if it is not available. This method makes use of the >- * partially constructed session stored in our setupImpl and completes its >- * construction >- */ >- public ServerSession getServerSession() { >- if (this.serverSession == null) { >- // PERF: Avoid synchronization. >- synchronized (this) { >- // DCL ok as isLoggedIn is volatile boolean, set after login is >- // complete. >- if (this.serverSession == null) { >- ClassLoader realLoader = setupImpl.getPersistenceUnitInfo().getClassLoader(); >- // splitProperties[0] contains supportedNonServerSessionProperties; [1] - all the rest. >- Map[] splitProperties = EntityManagerFactoryProvider.splitSpecifiedProperties(properties, supportedNonServerSessionProperties); >- // keep only non server session properties - the rest will be either cached in the server session or ignored >- properties = splitProperties[0]; >- Map serverSessionProperties = splitProperties[1]; >- // the call top setupImpl.deploy() finishes the session >- // creation >- ServerSession tempServerSession = setupImpl.deploy(realLoader, serverSessionProperties); >- // discard all but non server session properties from server session properties. >- Map tempProperties = EntityManagerFactoryProvider.keepSpecifiedProperties(tempServerSession.getProperties(), supportedNonServerSessionProperties); >- // properties override server session properties >- Map propertiesToProcess = EntityManagerFactoryProvider.mergeMaps(properties, tempProperties); >- processProperties(propertiesToProcess); >- this.serverSession = tempServerSession; >- } >- } >- } >- return this.serverSession; >- } >+ public EntityManagerFactoryImpl(EntityManagerSetupImpl setupImpl, Map properties) { >+ this.setupImpl = setupImpl; >+ this.properties = properties; >+ } > >- /** >- * Closes this factory, releasing any resources that might be held by this >- * factory. After invoking this method, all methods on the instance will >- * throw an {@link IllegalStateException}, except for {@link #isOpen}, which >- * will return <code>false</code>. >- */ >- public synchronized void close() { >- verifyOpen(); >- isOpen = false; >- // Do not invalidate the metaModel field >+ /** >+ * INTERNAL: Returns the ServerSession that the Factory will be using and >+ * initializes it if it is not available. This method makes use of the >+ * partially constructed session stored in our setupImpl and completes its >+ * construction >+ */ >+ public ServerSession getServerSession() { >+ if (this.serverSession == null) { >+ // PERF: Avoid synchronization. >+ synchronized (this) { >+ // DCL ok as isLoggedIn is volatile boolean, set after login is >+ // complete. >+ if (this.serverSession == null) { >+ ClassLoader realLoader = setupImpl.getPersistenceUnitInfo().getClassLoader(); >+ // splitProperties[0] contains >+ // supportedNonServerSessionProperties; [1] - all the rest. >+ Map[] splitProperties = EntityManagerFactoryProvider.splitSpecifiedProperties(properties, supportedNonServerSessionProperties); >+ // keep only non server session properties - the rest will >+ // be either cached in the server session or ignored >+ properties = splitProperties[0]; >+ Map serverSessionProperties = splitProperties[1]; >+ // the call top setupImpl.deploy() finishes the session >+ // creation >+ ServerSession tempServerSession = setupImpl.deploy(realLoader, serverSessionProperties); >+ // discard all but non server session properties from server >+ // session properties. >+ Map tempProperties = EntityManagerFactoryProvider.keepSpecifiedProperties(tempServerSession.getProperties(), supportedNonServerSessionProperties); >+ // properties override server session properties >+ Map propertiesToProcess = EntityManagerFactoryProvider.mergeMaps(properties, tempProperties); >+ processProperties(propertiesToProcess); >+ this.serverSession = tempServerSession; >+ } >+ } >+ } >+ return this.serverSession; >+ } >+ >+ /** >+ * Closes this factory, releasing any resources that might be held by this >+ * factory. After invoking this method, all methods on the instance will >+ * throw an {@link IllegalStateException}, except for {@link #isOpen}, which >+ * will return <code>false</code>. >+ */ >+ public synchronized void close() { >+ verifyOpen(); >+ isOpen = false; >+ // Do not invalidate the metaModel field > // (a reopened emf will re-populate the same metaModel) > // (a new persistence unit will generate a new metaModel) >- if (setupImpl != null) { >- // 260511 null check so that closing a EM >- // created from the constructor no longer throws a NPE >- setupImpl.undeploy(); >- } >- } >+ if (setupImpl != null) { >+ // 260511 null check so that closing a EM >+ // created from the constructor no longer throws a NPE >+ setupImpl.undeploy(); >+ } >+ } > >- /** >- * Indicates whether or not this factory is open. Returns <code>true</code> >- * until a call to {@link #close} is made. >- */ >- public boolean isOpen() { >- return isOpen; >- } >+ /** >+ * Indicates whether or not this factory is open. Returns <code>true</code> >+ * until a call to {@link #close} is made. >+ */ >+ public boolean isOpen() { >+ return isOpen; >+ } > >- /** >- * PUBLIC: Returns an EntityManager for this deployment. >- */ >- public EntityManager createEntityManager() { >- return createEntityManagerImpl(null); >- } >+ /** >+ * PUBLIC: Returns an EntityManager for this deployment. >+ */ >+ public EntityManager createEntityManager() { >+ return createEntityManagerImpl(null); >+ } > >- /** >- * PUBLIC: Returns an EntityManager for this deployment. >- */ >- public EntityManager createEntityManager(Map properties) { >- return createEntityManagerImpl(properties); >- } >+ /** >+ * PUBLIC: Returns an EntityManager for this deployment. >+ */ >+ public EntityManager createEntityManager(Map properties) { >+ return createEntityManagerImpl(properties); >+ } > >- protected EntityManagerImpl createEntityManagerImpl(Map properties) { >- verifyOpen(); >- ServerSession session = getServerSession(); >- if (!session.isLoggedIn()) { >- // PERF: Avoid synchronization. >- synchronized (session) { >- // DCL ok as isLoggedIn is volatile boolean, set after login is >- // complete. >- if (!session.isLoggedIn()) { >- session.login(); >- } >- } >- } >- return new EntityManagerImpl(this, properties); >- } >+ protected EntityManagerImpl createEntityManagerImpl(Map properties) { >+ verifyOpen(); >+ ServerSession session = getServerSession(); >+ if (!session.isLoggedIn()) { >+ // PERF: Avoid synchronization. >+ synchronized (session) { >+ // DCL ok as isLoggedIn is volatile boolean, set after login is >+ // complete. >+ if (!session.isLoggedIn()) { >+ session.login(); >+ } >+ } >+ } >+ return new EntityManagerImpl(this, properties); >+ } > >- protected void verifyOpen() { >- if (!this.isOpen) { >- throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager_factory")); >- } >- } >+ protected void verifyOpen() { >+ if (!this.isOpen) { >+ throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager_factory")); >+ } >+ } > >- protected void finalize() throws Throwable { >- if (isOpen()) { >- close(); >- } >- } >+ protected void finalize() throws Throwable { >+ if (isOpen()) { >+ close(); >+ } >+ } > >- /** >- * The method return user defined property passed in from >- * EntityManagerFactory. >- */ >- public Object getProperty(String name) { >- if (name == null) { >- return null; >- } >- if(properties != null) { >- Object value = properties.get(name); >- if(value != null) { >- return value; >- } >- } >- return getServerSession().getProperty(name); >- } >+ /** >+ * The method return user defined property passed in from >+ * EntityManagerFactory. >+ */ >+ public Object getProperty(String name) { >+ if (name == null) { >+ return null; >+ } >+ if (properties != null) { >+ Object value = properties.get(name); >+ if (value != null) { >+ return value; >+ } >+ } >+ return getServerSession().getProperty(name); >+ } > >- /** >- * Process all EntityManager properties. This allows all EntityManager >- * properties specified in the persistence.xml, factory properties, or >- * System properties to be preprocessed. This save the cost of processing >- * these properties each time an EntityManager is created, which can add >- * considerable overhead to both performance and concurrency as System >- * properties are a Hashtable and synchronized. >- * ATTENTION: >- * If you add a new property to be processed in this method please also add >- * the property's name to PersistenceUnitProperties.supportedNonServerSessionProperties >- */ >- protected void processProperties(Map properties) { >- String beginEarlyTransactionProperty = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.JOIN_EXISTING_TRANSACTION, properties, this.serverSession, true); >- if (beginEarlyTransactionProperty != null) { >- this.beginEarlyTransaction = "true".equalsIgnoreCase(beginEarlyTransactionProperty); >- } >- String referenceMode = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_REFERENCE_MODE, properties, this.serverSession, true); >- if (referenceMode != null) { >- this.referenceMode = ReferenceMode.valueOf(referenceMode); >- } >- String flushMode = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, properties, this.serverSession, true); >- if (flushMode != null) { >- this.flushMode = FlushModeType.valueOf(flushMode); >- } >- String closeOnCommit = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, properties, this.serverSession, true); >- if (closeOnCommit != null) { >- this.closeOnCommit = "true".equalsIgnoreCase(closeOnCommit); >- } >- String persistOnCommit = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_PERSIST_ON_COMMIT, properties, this.serverSession, true); >- if (persistOnCommit != null) { >- this.persistOnCommit = "true".equalsIgnoreCase(persistOnCommit); >- } >+ /** >+ * Process all EntityManager properties. This allows all EntityManager >+ * properties specified in the persistence.xml, factory properties, or >+ * System properties to be preprocessed. This save the cost of processing >+ * these properties each time an EntityManager is created, which can add >+ * considerable overhead to both performance and concurrency as System >+ * properties are a Hashtable and synchronized. ATTENTION: If you add a new >+ * property to be processed in this method please also add the property's >+ * name to PersistenceUnitProperties.supportedNonServerSessionProperties >+ */ >+ protected void processProperties(Map properties) { >+ String beginEarlyTransactionProperty = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.JOIN_EXISTING_TRANSACTION, properties, this.serverSession, true); >+ if (beginEarlyTransactionProperty != null) { >+ this.beginEarlyTransaction = "true".equalsIgnoreCase(beginEarlyTransactionProperty); >+ } >+ String referenceMode = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_REFERENCE_MODE, properties, this.serverSession, true); >+ if (referenceMode != null) { >+ this.referenceMode = ReferenceMode.valueOf(referenceMode); >+ } >+ String flushMode = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_FLUSH_MODE, properties, this.serverSession, true); >+ if (flushMode != null) { >+ this.flushMode = FlushModeType.valueOf(flushMode); >+ } >+ String closeOnCommit = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT, properties, this.serverSession, true); >+ if (closeOnCommit != null) { >+ this.closeOnCommit = "true".equalsIgnoreCase(closeOnCommit); >+ } >+ String persistOnCommit = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_PERSIST_ON_COMMIT, properties, this.serverSession, true); >+ if (persistOnCommit != null) { >+ this.persistOnCommit = "true".equalsIgnoreCase(persistOnCommit); >+ } > String commitWithoutPersist = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.PERSISTENCE_CONTEXT_COMMIT_WITHOUT_PERSIST_RULES, properties, this.serverSession, true); > if (commitWithoutPersist != null) { > this.commitWithoutPersistRules = "true".equalsIgnoreCase(commitWithoutPersist); > } >- String shouldValidateExistence = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.VALIDATE_EXISTENCE, properties, this.serverSession, true); >- if (shouldValidateExistence != null) { >- this.shouldValidateExistence = "true".equalsIgnoreCase(shouldValidateExistence); >- } >- String flushClearCache = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.FLUSH_CLEAR_CACHE, properties, this.serverSession, true); >- if (flushClearCache != null) { >- this.flushClearCache = flushClearCache; >- } >- } >+ String shouldValidateExistence = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.VALIDATE_EXISTENCE, properties, this.serverSession, true); >+ if (shouldValidateExistence != null) { >+ this.shouldValidateExistence = "true".equalsIgnoreCase(shouldValidateExistence); >+ } >+ String flushClearCache = PropertiesHandler.getPropertyValueLogDebug(EntityManagerProperties.FLUSH_CLEAR_CACHE, properties, this.serverSession, true); >+ if (flushClearCache != null) { >+ this.flushClearCache = flushClearCache; >+ } >+ } > >- /** >- * Return default join existing transaction property, allows reading through >- * write connection. >- */ >- public boolean getBeginEarlyTransaction() { >- return beginEarlyTransaction; >- } >+ /** >+ * Return default join existing transaction property, allows reading through >+ * write connection. >+ */ >+ public boolean getBeginEarlyTransaction() { >+ return beginEarlyTransaction; >+ } > >- /** >- * Set default join existing transaction property, allows reading through >- * write connection. >- */ >- public void setBeginEarlyTransaction(boolean beginEarlyTransaction) { >- this.beginEarlyTransaction = beginEarlyTransaction; >- } >+ /** >+ * Set default join existing transaction property, allows reading through >+ * write connection. >+ */ >+ public void setBeginEarlyTransaction(boolean beginEarlyTransaction) { >+ this.beginEarlyTransaction = beginEarlyTransaction; >+ } > >- /** >- * Return default property, allows flush before query to be avoided. >- */ >- public FlushModeType getFlushMode() { >- return flushMode; >- } >+ /** >+ * Return default property, allows flush before query to be avoided. >+ */ >+ public FlushModeType getFlushMode() { >+ return flushMode; >+ } > >- /** >- * Set default property, allows flush before query to be avoided. >- */ >- public void setFlushMode(FlushModeType flushMode) { >- this.flushMode = flushMode; >- } >+ /** >+ * Set default property, allows flush before query to be avoided. >+ */ >+ public void setFlushMode(FlushModeType flushMode) { >+ this.flushMode = flushMode; >+ } > >- /** >- * Return default property, allows weak unit of work references. >- */ >- public ReferenceMode getReferenceMode() { >- return referenceMode; >- } >+ /** >+ * Return default property, allows weak unit of work references. >+ */ >+ public ReferenceMode getReferenceMode() { >+ return referenceMode; >+ } > >- /** >- * Set default property, allows weak unit of work references. >- */ >- public void setReferenceMode(ReferenceMode referenceMode) { >- this.referenceMode = referenceMode; >- } >+ /** >+ * Set default property, allows weak unit of work references. >+ */ >+ public void setReferenceMode(ReferenceMode referenceMode) { >+ this.referenceMode = referenceMode; >+ } > >- /** >- * Return default property to avoid resuming unit of work if going to be >- * closed on commit anyway. >- */ >- public boolean getCloseOnCommit() { >- return closeOnCommit; >- } >+ /** >+ * Return default property to avoid resuming unit of work if going to be >+ * closed on commit anyway. >+ */ >+ public boolean getCloseOnCommit() { >+ return closeOnCommit; >+ } > >- /** >- * Set default property to avoid resuming unit of work if going to be closed >- * on commit anyway. >- */ >- public void setCloseOnCommit(boolean closeOnCommit) { >- this.closeOnCommit = closeOnCommit; >- } >+ /** >+ * Set default property to avoid resuming unit of work if going to be closed >+ * on commit anyway. >+ */ >+ public void setCloseOnCommit(boolean closeOnCommit) { >+ this.closeOnCommit = closeOnCommit; >+ } > >- /** >- * Return default property to avoid discover new objects in unit of work if >- * application always uses persist. >- */ >- public boolean getPersistOnCommit() { >- return persistOnCommit; >- } >+ /** >+ * Return default property to avoid discover new objects in unit of work if >+ * application always uses persist. >+ */ >+ public boolean getPersistOnCommit() { >+ return persistOnCommit; >+ } > > /** >- * Return interface providing access to utility methods >- * for the persistence unit. >+ * Return interface providing access to utility methods for the persistence >+ * unit. >+ * > * @return PersistenceUnitUtil interface >- * @throws IllegalStateException if the entity manager factory >- * has been closed. >+ * @throws IllegalStateException >+ * if the entity manager factory has been closed. > */ >- public PersistenceUnitUtil getPersistenceUnitUtil(){ >+ public PersistenceUnitUtil getPersistenceUnitUtil() { > return this; > } > > /** >- * Set default property to avoid discover new objects in unit of work if >- * application always uses persist. >- */ >- public void setPersistOnCommit(boolean persistOnCommit) { >- this.persistOnCommit = persistOnCommit; >- } >+ * Set default property to avoid discover new objects in unit of work if >+ * application always uses persist. >+ */ >+ public void setPersistOnCommit(boolean persistOnCommit) { >+ this.persistOnCommit = persistOnCommit; >+ } > > /** >- * Return default property to avoid discover new objects in unit of work if application always uses persist. >+ * Return default property to avoid discover new objects in unit of work if >+ * application always uses persist. > */ > public boolean getCommitWithoutPersistRules() { > return commitWithoutPersistRules; > } >- >+ > /** >- * Set default property to avoid discover new objects in unit of work if application always uses persist. >+ * Set default property to avoid discover new objects in unit of work if >+ * application always uses persist. > */ > public void setCommitWithoutPersistRules(boolean commitWithoutPersistRules) { > this.commitWithoutPersistRules = commitWithoutPersistRules; > } >+ > /** >- * Return the default FlashClearCache mode to be used. >- * Relevant only in case call to flush method followed by call to clear method. >- * @see org.eclipse.persistence.config.FlushClearCache >- */ >- public String getFlushClearCache() { >- return flushClearCache; >- } >+ * Return the default FlashClearCache mode to be used. Relevant only in case >+ * call to flush method followed by call to clear method. >+ * >+ * @see org.eclipse.persistence.config.FlushClearCache >+ */ >+ public String getFlushClearCache() { >+ return flushClearCache; >+ } > >- /** >- * Set the default FlashClearCache mode to be used. Relevant only in case >- * call to flush method followed by call to clear method. >- * >- * @see org.eclipse.persistence.config.FlushClearCache >- */ >- public void setFlushClearCache(String flushClearCache) { >- this.flushClearCache = flushClearCache; >- } >+ /** >+ * Set the default FlashClearCache mode to be used. Relevant only in case >+ * call to flush method followed by call to clear method. >+ * >+ * @see org.eclipse.persistence.config.FlushClearCache >+ */ >+ public void setFlushClearCache(String flushClearCache) { >+ this.flushClearCache = flushClearCache; >+ } > >- /** >- * Return the default to determine if does-exist should be performed on >- * persist. >- */ >- public boolean shouldValidateExistence() { >- return shouldValidateExistence; >- } >+ /** >+ * Return the default to determine if does-exist should be performed on >+ * persist. >+ */ >+ public boolean shouldValidateExistence() { >+ return shouldValidateExistence; >+ } > >- /** >- * Set the default to determine if does-exist should be performed on >- * persist. >- */ >- public void setShouldValidateExistence(boolean shouldValidateExistence) { >- this.shouldValidateExistence = shouldValidateExistence; >- } >+ /** >+ * Set the default to determine if does-exist should be performed on >+ * persist. >+ */ >+ public void setShouldValidateExistence(boolean shouldValidateExistence) { >+ this.shouldValidateExistence = shouldValidateExistence; >+ } > >- public Cache getCache() { >- verifyOpen(); >- if (myCache == null) { >- ServerSession session = this.getServerSession(); >- myCache = new CacheImpl(this, session.getIdentityMapAccessor()); >- } >- return myCache; >- } >+ public Cache getCache() { >+ verifyOpen(); >+ if (myCache == null) { >+ ServerSession session = this.getServerSession(); >+ myCache = new CacheImpl(this, session.getIdentityMapAccessor()); >+ } >+ return myCache; >+ } > >- /** >- * @see javax.persistence.EntityManagerFactory#getProperties() >- * @since Java Persistence API 2.0 >- */ >- public Map<String, Object> getProperties() { >- if(!this.isOpen()) { >- throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager_factory")); >- } >- return Collections.unmodifiableMap(EntityManagerFactoryProvider.mergeMaps(properties, this.getServerSession().getProperties())); >- } >+ /** >+ * @see javax.persistence.EntityManagerFactory#getProperties() >+ * @since Java Persistence API 2.0 >+ */ >+ public Map<String, Object> getProperties() { >+ if (!this.isOpen()) { >+ throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager_factory")); >+ } >+ return Collections.unmodifiableMap(EntityManagerFactoryProvider.mergeMaps(properties, this.getServerSession().getProperties())); >+ } > >- /** >- * @see javax.persistence.EntityManagerFactory#getCriteriaBuilder() >- * @since Java Persistence 2.0 >- */ >- public CriteriaBuilder getCriteriaBuilder() { >+ /** >+ * @see javax.persistence.EntityManagerFactory#getCriteriaBuilder() >+ * @since Java Persistence 2.0 >+ */ >+ public CriteriaBuilder getCriteriaBuilder() { > return new CriteriaBuilderImpl(this.getMetamodel()); >- } >+ } > > /** >- * Return an instance of Metamodel interface for access to the >- * metamodel of the persistence unit. >+ * Return an instance of Metamodel interface for access to the metamodel of >+ * the persistence unit. >+ * > * @return Metamodel instance >- * @throws IllegalStateException if the entity manager factory has >- * been closed. >+ * @throws IllegalStateException >+ * if the entity manager factory has been closed. > * @see javax.persistence.EntityManagerFactory#getMetamodel() > * @since Java Persistence 2.0 > */ > public Metamodel getMetamodel() { >- if(!this.isOpen()) { >+ if (!this.isOpen()) { > throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager_factory")); > } > return this.setupImpl.getMetamodel(); > } > > /** >- * INTERNAL: >- * Convenience function to allow us to reset the Metamodel >- * in the possible case that we want to regenerate it. >- * This function is outside of the JPA 2.0 specification. >+ * INTERNAL: Convenience function to allow us to reset the Metamodel in the >+ * possible case that we want to regenerate it. This function is outside of >+ * the JPA 2.0 specification. >+ * > * @param aMetamodel >- * @since Java Persistence 2.0 >+ * @since Java Persistence 2.0 > */ > public void setMetamodel(Metamodel aMetamodel) { >- if(!this.isOpen()) { >+ if (!this.isOpen()) { > throw new IllegalStateException(ExceptionLocalization.buildMessage("operation_on_closed_entity_manager_factory")); > } > this.setupImpl.setMetamodel(aMetamodel); > } >- >+ > /** >- * Determine the load state of a given persistent attribute >- * of an entity belonging to the persistence unit. >- * @param entity containing the attribute >- * @param attributeName name of attribute whose load state is >- * to be determined >- * @return false if entity's state has not been loaded or >- * if the attribute state has not been loaded, otherwise true >+ * Determine the load state of a given persistent attribute of an entity >+ * belonging to the persistence unit. >+ * >+ * @param entity >+ * containing the attribute >+ * @param attributeName >+ * name of attribute whose load state is to be determined >+ * @return false if entity's state has not been loaded or if the attribute >+ * state has not been loaded, otherwise true > */ >- public boolean isLoaded(Object entity, String attributeName){ >- if (EntityManagerFactoryImpl.isLoaded(entity, attributeName, serverSession).equals(Boolean.valueOf(true))){ >+ public boolean isLoaded(Object entity, String attributeName) { >+ if (EntityManagerFactoryImpl.isLoaded(entity, attributeName, serverSession).equals(Boolean.valueOf(true))) { > return true; > } > return false; > } >- >+ > /** >- * Determine the load state of an entity belonging to the >- * persistence unit. >- * This method can be used to determine the load state >- * of an entity passed as a reference. An entity is >- * considered loaded if all attributes for which FetchType >- * EAGER has been specified have been loaded. >- * The isLoaded(Object, String) method should be used to >- * determine the load state of an attribute. >- * Not doing so might lead to unintended loading of state. >- * @param entity whose load state is to be determined >+ * Determine the load state of an entity belonging to the persistence unit. >+ * This method can be used to determine the load state of an entity passed >+ * as a reference. An entity is considered loaded if all attributes for >+ * which FetchType EAGER has been specified have been loaded. The >+ * isLoaded(Object, String) method should be used to determine the load >+ * state of an attribute. Not doing so might lead to unintended loading of >+ * state. >+ * >+ * @param entity >+ * whose load state is to be determined > * @return false if the entity has not been loaded, else true. > */ >- public boolean isLoaded(Object entity){ >- if (EntityManagerFactoryImpl.isLoaded(entity, serverSession).equals(Boolean.valueOf(true))){ >+ public boolean isLoaded(Object entity) { >+ if (EntityManagerFactoryImpl.isLoaded(entity, serverSession).equals(Boolean.valueOf(true))) { > return true; > } > return false; > } >- >+ > /** >- * Returns the id of the entity. >- * A generated id is not guaranteed to be available until after >- * the database insert has occurred. >- * Returns null if the entity does not yet have an id >- * @param entity >- * @return id of the entity >- * @throws IllegalStateException if the entity is found not to be >- * an entity. >+ * Returns the id of the entity. A generated id is not guaranteed to be >+ * available until after the database insert has occurred. Returns null if >+ * the entity does not yet have an id >+ * >+ * @param entity >+ * @return id of the entity >+ * @throws IllegalStateException >+ * if the entity is found not to be an entity. > */ >- public Object getIdentifier(Object entity){ >+ public Object getIdentifier(Object entity) { > return EntityManagerFactoryImpl.getIdentifier(entity, serverSession); > } >- >+ > /** >- * Determine the load state of a given persistent attribute >- * of an entity belonging to the persistence unit. >- * @param entity containing the attribute >- * @param attributeName name of attribute whose load state is >- * to be determined >- * @return false if entity's state has not been loaded or >- * if the attribute state has not been loaded, otherwise true >+ * Determine the load state of a given persistent attribute of an entity >+ * belonging to the persistence unit. >+ * >+ * @param entity >+ * containing the attribute >+ * @param attributeName >+ * name of attribute whose load state is to be determined >+ * @return false if entity's state has not been loaded or if the attribute >+ * state has not been loaded, otherwise true > */ >- public static Boolean isLoaded(Object entity, String attributeName, AbstractSession session){ >+ public static Boolean isLoaded(Object entity, String attributeName, AbstractSession session) { > ClassDescriptor descriptor = session.getDescriptor(entity); >- if (descriptor == null){ >+ if (descriptor == null) { > return null; > } > DatabaseMapping mapping = descriptor.getMappingForAttributeName(attributeName); >- if (mapping == null){ >+ if (mapping == null) { > return null; > } > return isLoaded(entity, attributeName, mapping); > } >- >+ > /** >- * Check whether a named attribute on a given entity with a given mapping has been loaded. >+ * Check whether a named attribute on a given entity with a given mapping >+ * has been loaded. > * >- * This method will check the valueholder or indirect collection for LAZY ForeignReferenceMappings >- * to see if has been instantiated and otherwise check the fetch group. >+ * This method will check the valueholder or indirect collection for LAZY >+ * ForeignReferenceMappings to see if has been instantiated and otherwise >+ * check the fetch group. >+ * > * @param entity > * @param attributeName > * @param mapping > * @return > */ >- public static boolean isLoaded(Object entity, String attributeName, DatabaseMapping mapping){ >- if (mapping.isForeignReferenceMapping()){ >- if (((ForeignReferenceMapping)mapping).isLazy()){ >+ public static boolean isLoaded(Object entity, String attributeName, DatabaseMapping mapping) { >+ if (mapping.isForeignReferenceMapping()) { >+ if (((ForeignReferenceMapping) mapping).isLazy()) { > Object value = mapping.getAttributeValueFromObject(entity); >- IndirectionPolicy policy = ((ForeignReferenceMapping)mapping).getIndirectionPolicy(); >+ IndirectionPolicy policy = ((ForeignReferenceMapping) mapping).getIndirectionPolicy(); > return policy.objectIsInstantiated(value); > } > } > >- if (entity instanceof FetchGroupTracker){ >- return ((FetchGroupTracker)entity)._persistence_isAttributeFetched(attributeName); >+ if (entity instanceof FetchGroupTracker) { >+ return ((FetchGroupTracker) entity)._persistence_isAttributeFetched(attributeName); > } else { > return true; > } > } >- >+ > /** >- * Determine the load state of an entity belonging to the >- * persistence unit. >- * This method can be used to determine the load state >- * of an entity passed as a reference. An entity is >- * considered loaded if all attributes for which FetchType >- * EAGER has been specified have been loaded. >- * The isLoaded(Object, String) method should be used to >- * determine the load state of an attribute. >- * Not doing so might lead to unintended loading of state. >- * @param entity whose load state is to be determined >+ * Determine the load state of an entity belonging to the persistence unit. >+ * This method can be used to determine the load state of an entity passed >+ * as a reference. An entity is considered loaded if all attributes for >+ * which FetchType EAGER has been specified have been loaded. The >+ * isLoaded(Object, String) method should be used to determine the load >+ * state of an attribute. Not doing so might lead to unintended loading of >+ * state. >+ * >+ * @param entity >+ * whose load state is to be determined > * @return false if the entity has not been loaded, else true. > */ >- public static Boolean isLoaded(Object entity, AbstractSession session){ >+ public static Boolean isLoaded(Object entity, AbstractSession session) { > ClassDescriptor descriptor = session.getDescriptor(entity); >- if (descriptor == null){ >+ if (descriptor == null) { > return null; > } > List<DatabaseMapping> mappings = descriptor.getMappings(); > Iterator<DatabaseMapping> i = mappings.iterator(); >- while (i.hasNext()){ >+ while (i.hasNext()) { > DatabaseMapping mapping = i.next(); >- if (!mapping.isLazy() && !isLoaded(entity, mapping.getAttributeName(), mapping)){ >+ if (!mapping.isLazy() && !isLoaded(entity, mapping.getAttributeName(), mapping)) { > return false; > } > } > return true; > } >- >+ > /** >- * Returns the id of the entity. >- * A generated id is not guaranteed to be available until after >- * the database insert has occurred. >- * Returns null if the entity does not yet have an id >- * @param entity >- * @return id of the entity >- * @throws IllegalStateException if the entity is found not to be >- * an entity. >+ * Returns the id of the entity. A generated id is not guaranteed to be >+ * available until after the database insert has occurred. Returns null if >+ * the entity does not yet have an id >+ * >+ * @param entity >+ * @return id of the entity >+ * @throws IllegalStateException >+ * if the entity is found not to be an entity. > */ >- public static Object getIdentifier(Object entity, AbstractSession session){ >+ public static Object getIdentifier(Object entity, AbstractSession session) { > ClassDescriptor descriptor = session.getDescriptor(entity); >- if (descriptor == null){ >- throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_persistence_util_non_persistent_class ", new Object[]{entity})); >+ if (descriptor == null) { >+ throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_persistence_util_non_persistent_class ", new Object[] { entity })); > } >- if (descriptor.getCMPPolicy() != null){ >+ if (descriptor.getCMPPolicy() != null) { > return descriptor.getCMPPolicy().createPrimaryKeyInstance(entity, session); > } else { >- throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_persistence_util_non_persistent_class ", new Object[]{entity})); >+ throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa_persistence_util_non_persistent_class ", new Object[] { entity })); > } > } > >Index: jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/jpa/JpaCache.java >=================================================================== >--- jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/jpa/JpaCache.java (revision 0) >+++ jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/jpa/JpaCache.java (revision 0) >@@ -0,0 +1,144 @@ >+/******************************************************************************* >+ * Copyright (c) 1998, 2010 Oracle. All rights reserved. >+ * This program and the accompanying materials are made available under the >+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 >+ * which accompanies this distribution. >+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html >+ * and the Eclipse Distribution License is available at >+ * http://www.eclipse.org/org/documents/edl-v10.php. >+ * >+ * Contributors: >+ * James Sutherland = 1.0 - Initial contribution >+ ******************************************************************************/ >+package org.eclipse.persistence.jpa; >+ >+import javax.persistence.Cache; >+ >+/** >+ * Extends JPA Cache interface with additional EclipseLink API. >+ * @author James Sutherland >+ */ >+public interface JpaCache extends Cache { >+ >+ /** >+ * ADVANCED: >+ * Resets the entire Object cache, and the Query cache. >+ * <p> NOTE: Be careful using this method. This method blows away both this session's and its parent's caches. >+ * This includes the server cache or any other cache. This throws away any Objects that have been read in. >+ * Extreme caution should be used before doing this because Object identity will no longer >+ * be maintained for any Objects currently read in. This should only be called >+ * if the application knows that it no longer has references to Objects held in the cache. >+ */ >+ void clear(); >+ >+ /** >+ * ADVANCED: >+ * Resets the cache for only the instances of the given Class type. >+ * For inheritance the user must make sure that they only use the root class, >+ * clearing a subclass cache is not allowed (as they share their parents cache). >+ * <p> NOTE: Caution must be used in doing this to ensure that the Objects within the cache >+ * are not referenced from other Objects of other classes or from the application. >+ */ >+ void clear(Class cls); >+ >+ /** >+ * Clear all the query caches. >+ */ >+ void clearQueryCache(); >+ >+ /** >+ * Clear the named query cache associated with the query name. >+ */ >+ void clearQueryCache(String queryName); >+ >+ /** >+ * Returns the remaining life of the given Object (in milliseconds). This method is associated with use of >+ * cache invalidation feature and returns the difference between the next expiry >+ * time of the Object and its read time. The method will return 0 for invalidated Objects. >+ */ >+ long timeToLive(Object object); >+ >+ /** >+ * Returns true if the Object with the same id and Class type of the >+ * the given Object is valid in the cache. >+ */ >+ boolean isValid(Object object); >+ >+ /** >+ * Returns true if the Object with the id and Class type is valid in the cache. >+ */ >+ boolean isValid(Class cls, Object id); >+ >+ /** >+ * Used to print all the Objects in the cache. >+ * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level. >+ */ >+ void print(); >+ >+ /** >+ * Used to print all the Objects in the cache of the Class type. >+ * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level. >+ */ >+ void print(Class cls); >+ >+ /** >+ * Used to print all the currently locked cache keys in the cache. >+ * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level. >+ */ >+ void printLocks(); >+ >+ /** >+ * This can be used to help debugging an Object identity problem. >+ * An Object identity problem is when an Object in the cache references an >+ * Object that is not in the cache. This method will validate that all cached >+ * Objects are in a correct state. >+ */ >+ void validate(); >+ >+ /** >+ * Returns the Object from the cache map with the id >+ * and Class type. >+ */ >+ Object getObject(Class cls, Object id); >+ >+ /** >+ * ADVANCED: >+ * Puts the given Object into the cache. >+ * This is a very advanced method, and caution should be used in adding objects to the cache >+ * as other objects may have relationships to previous object, or this object may have >+ * relationships to other objects. >+ */ >+ Object putObject(Object object); >+ >+ /** >+ * ADVANCED: >+ * Removes the Object from the cache. >+ * <p> NOTE: Caution should be used when calling to avoid violating Object identity. >+ * The application should only call this if its known that no references to the Object exist. >+ */ >+ Object removeObject(Object object); >+ >+ /** >+ * ADVANCED: >+ * Removes the Object with the id and Class type from the cache. >+ * <p> NOTE: Caution should be used when calling to avoid violating Object identity. >+ * The application should only call this if its known that no references to the Object exist. >+ */ >+ Object removeObject(Class cls, Object id); >+ >+ /** >+ * Returns true if the cache contains an Object with the same id and Class type of the given object. >+ */ >+ boolean contains(Object object); >+ >+ /** >+ * Sets an Object to be invalid in the cache. >+ */ >+ void evict(Object object); >+ >+ /** >+ * Returns the object's Id. >+ */ >+ Object getId(Object object); >+ >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 298985
:
155445
|
155774
|
156022
|
157311
| 157786 |
226667