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 @@
*
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 @@
*
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 usedObjectReferenceMappings = new HashSet();
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.
+ * 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).
+ *
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.
+ *
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.
+ *
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 supportedNonServerSessionProperties = PersistenceUnitProperties.getSupportedNonServerSessionProperties();
-
- /**
- * Default join existing transaction property, allows reading through write
- * connection.
- */
- protected boolean beginEarlyTransaction;
+ protected static final Set 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 false
.
- */
- 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 false
.
+ */
+ 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 true
- * until a call to {@link #close} is made.
- */
- public boolean isOpen() {
- return isOpen;
- }
+ /**
+ * Indicates whether or not this factory is open. Returns true
+ * 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 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 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 mappings = descriptor.getMappings();
Iterator 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.
+ * 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).
+ *
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.
+ *
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.
+ *
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);
+
+}