| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.queries; |
| |
| import java.security.AccessController; |
| import java.security.PrivilegedActionException; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.exceptions.ValidationException; |
| import org.eclipse.persistence.expressions.Expression; |
| import org.eclipse.persistence.internal.expressions.ForUpdateClause; |
| import org.eclipse.persistence.internal.expressions.QueryKeyExpression; |
| import org.eclipse.persistence.internal.identitymaps.CacheKey; |
| import org.eclipse.persistence.internal.queries.ContainerPolicy; |
| import org.eclipse.persistence.internal.queries.JoinedAttributeManager; |
| import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; |
| import org.eclipse.persistence.internal.security.PrivilegedClassForName; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.internal.sessions.MergeManager; |
| import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| |
| /** |
| * <p><b>Purpose</b>: |
| * Abstract class for all read queries that build objects and potentially manipulate |
| * the TopLink cache. |
| * |
| * <p><b>Description</b>: |
| * Contains common behavior for all read queries building objects. |
| * |
| * @author Gordon Yorke |
| * @since TopLink Essentials |
| */ |
| public abstract class ObjectBuildingQuery extends ReadQuery { |
| |
| /** The class of the target objects to be read from the database. */ |
| protected Class<?> referenceClass; |
| protected String referenceClassName; |
| |
| /** Allows for the resulting objects to be refresh with the data from the database. */ |
| protected boolean shouldRefreshIdentityMapResult; |
| protected boolean shouldRefreshRemoteIdentityMapResult; |
| |
| /** INTERNAL: for bug 2612601 allow ability not to register results in UOW. */ |
| protected boolean shouldRegisterResultsInUnitOfWork = true; |
| |
| /** Used for pessimistic locking. */ |
| protected ForUpdateClause lockingClause; |
| public static final short NO_LOCK = 0; |
| public static final short LOCK = 1; |
| public static final short LOCK_NOWAIT = 2; |
| // allow pessimistic locking policy to be used |
| public static final short DEFAULT_LOCK_MODE = -1; |
| |
| /** |
| * 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; |
| |
| /** |
| * Added for Exclusive Connection (VPD) support see accessor for information |
| */ |
| protected boolean shouldUseExclusiveConnection = false; |
| |
| /** |
| * INTERNAL: This is the key for accessing unregistered and locked result in the query's properties. |
| * The uow and QueryBaseValueHolder use this property to record and to retrieve the result respectively. |
| */ |
| public static final String LOCK_RESULT_PROPERTY = "LOCK_RESULT"; |
| |
| /** PERF: Store if the query originally used the default lock mode. */ |
| protected boolean wasDefaultLockMode = false; |
| |
| /** |
| * INTERNAL: If primary key is null ObjectBuilder.buildObject returns null |
| * in case this flag is set to true (instead of throwing exception). |
| */ |
| protected boolean shouldBuildNullForNullPk; |
| |
| /** |
| * When reading across relationships, queries may be set to acquire deferred locks |
| * This is used to ensure any Eagerly fetched object that is the target of a relationship |
| * with an object the acquires deferred locks behaves the same as its owner |
| */ |
| protected Boolean requiresDeferredLocks = null; |
| |
| /** was a check early return completed */ |
| protected boolean isCacheCheckComplete; |
| |
| protected Map<Object, CacheKey> prefetchedCacheKeys; |
| |
| /** |
| * INTERNAL: |
| * Initialize the state of the query |
| */ |
| protected ObjectBuildingQuery() { |
| this.shouldRefreshIdentityMapResult = false; |
| this.isCacheCheckComplete = false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Clone the query |
| */ |
| @Override |
| public Object clone() { |
| ObjectBuildingQuery cloneQuery = (ObjectBuildingQuery) super.clone(); |
| cloneQuery.isCacheCheckComplete = this.isCacheCheckComplete; |
| return cloneQuery; |
| } |
| /** |
| * INTERNAL |
| * Used to give the subclasses opportunity to copy aspects of the cloned query |
| * to the original query. |
| */ |
| @Override |
| protected void clonedQueryExecutionComplete(DatabaseQuery query, AbstractSession session) { |
| super.clonedQueryExecutionComplete(query, session); |
| //reset cache check flag for next execution. |
| this.isCacheCheckComplete = false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Convert all the class-name-based settings in this query to actual class-based |
| * settings. This method is used when converting a project that has been built |
| * with class names to a project with classes. |
| */ |
| @Override |
| public void convertClassNamesToClasses(ClassLoader classLoader){ |
| super.convertClassNamesToClasses(classLoader); |
| Class<?> referenceClass = null; |
| try{ |
| if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ |
| try { |
| referenceClass = AccessController.doPrivileged(new PrivilegedClassForName<>(getReferenceClassName(), true, classLoader)); |
| } catch (PrivilegedActionException exception) { |
| throw ValidationException.classNotFoundWhileConvertingClassNames(getReferenceClassName(), exception.getException()); |
| } |
| } else { |
| referenceClass = PrivilegedAccessHelper.getClassForName(getReferenceClassName(), true, classLoader); |
| } |
| } catch (ClassNotFoundException exc){ |
| throw ValidationException.classNotFoundWhileConvertingClassNames(getReferenceClassName(), exc); |
| } |
| setReferenceClass(referenceClass); |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if this query originally used the default lock mode. |
| */ |
| protected boolean wasDefaultLockMode() { |
| return wasDefaultLockMode; |
| } |
| |
| /** |
| * INTERNAL: |
| * Set if this query originally used the default lock mode. |
| */ |
| protected void setWasDefaultLockMode(boolean wasDefaultLockMode) { |
| this.wasDefaultLockMode = wasDefaultLockMode; |
| } |
| |
| /** |
| * INTERNAL: |
| * Clone the query, including its selection criteria. |
| * <p> |
| * Normally selection criteria are not cloned here as they are cloned |
| * later on during prepare. |
| */ |
| public Object deepClone() { |
| return clone(); |
| } |
| |
| /** |
| * INTERNAL: |
| * Copy all setting from the query. |
| * This is used to morph queries from one type to the other. |
| * By default this calls prepareFromQuery, but additional properties may be required |
| * to be copied as prepareFromQuery only copies properties that affect the SQL. |
| */ |
| @Override |
| public void copyFromQuery(DatabaseQuery query) { |
| super.copyFromQuery(query); |
| if (query.isObjectBuildingQuery()) { |
| ObjectBuildingQuery readQuery = (ObjectBuildingQuery)query; |
| this.shouldBuildNullForNullPk = readQuery.shouldBuildNullForNullPk; |
| this.shouldRefreshIdentityMapResult = readQuery.shouldRefreshIdentityMapResult; |
| this.shouldRefreshRemoteIdentityMapResult = readQuery.shouldRefreshRemoteIdentityMapResult; |
| this.shouldRegisterResultsInUnitOfWork = readQuery.shouldRegisterResultsInUnitOfWork; |
| this.shouldUseExclusiveConnection = readQuery.shouldUseExclusiveConnection; |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Set the properties needed to be cascaded into the custom query including the translation row. |
| * This is used only for primary key queries, as the descriptor query manager |
| * stores a predefined query for this query to avoid having to re-prepare and allow for customization. |
| */ |
| @Override |
| protected void prepareCustomQuery(DatabaseQuery customQuery) { |
| ((ObjectBuildingQuery)customQuery).isCacheCheckComplete = this.isCacheCheckComplete; |
| } |
| |
| /** |
| * INTERNAL: |
| * Prepare the query from the prepared query. |
| * This allows a dynamic query to prepare itself directly from a prepared query instance. |
| * This is used in the EJBQL parse cache to allow preparsed queries to be used to prepare |
| * dynamic queries. |
| * This only copies over properties that are configured through EJBQL. |
| */ |
| @Override |
| public void prepareFromQuery(DatabaseQuery query) { |
| super.prepareFromQuery(query); |
| if (query.isObjectBuildingQuery()) { |
| ObjectBuildingQuery objectQuery = (ObjectBuildingQuery)query; |
| this.referenceClass = objectQuery.referenceClass; |
| this.referenceClassName = objectQuery.referenceClassName; |
| this.lockingClause = objectQuery.lockingClause; |
| this.wasDefaultLockMode = objectQuery.wasDefaultLockMode; |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * When unset means perform read normally and dont do refresh. |
| */ |
| public void dontRefreshIdentityMapResult() { |
| setShouldRefreshIdentityMapResult(false); |
| } |
| |
| /** |
| * PUBLIC: |
| * When unset means perform read normally and dont do refresh. |
| */ |
| public void dontRefreshRemoteIdentityMapResult() { |
| setShouldRefreshRemoteIdentityMapResult(false); |
| } |
| |
| /** |
| * INTERNAL: |
| * Indicates whether a FetchGroup will be applied to the query. |
| */ |
| public boolean hasExecutionFetchGroup() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Returns FetchGroup that will be applied to the query. |
| * Note that the returned fetchGroup may be updated during preProcess. |
| */ |
| public FetchGroup getExecutionFetchGroup() { |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Returns FetchGroup that will be applied to the query. |
| * Note that the returned fetchGroup may be updated during preProcess. |
| */ |
| public FetchGroup getExecutionFetchGroup(ClassDescriptor descriptor) { |
| return null; |
| } |
| |
| /** |
| * Return the load group set in the query. |
| */ |
| public LoadGroup getLoadGroup() { |
| return null; |
| } |
| |
| /** |
| * PUBLIC: Return the current locking mode. |
| */ |
| public short getLockMode() { |
| if (lockingClause == null) { |
| return DEFAULT_LOCK_MODE; |
| } else { |
| return lockingClause.getLockMode(); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Return all of the rows fetched by the query, used for 1-m joining. |
| */ |
| public List getDataResults() { |
| return null; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the time this query actually went to the database |
| */ |
| public long getExecutionTime() { |
| return executionTime; |
| } |
| |
| public Map<Object, CacheKey> getPrefetchedCacheKeys() { |
| return prefetchedCacheKeys; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the primary key stored in this query if there is one |
| * This is overridden by subclasses that actually hold a primary key |
| * |
| * @see ReadObjectQuery |
| */ |
| protected Object getQueryPrimaryKey(){ |
| return null; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return the reference class of the query. |
| */ |
| @Override |
| public Class<?> getReferenceClass() { |
| return referenceClass; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return the reference class of the query. |
| */ |
| @Override |
| public String getReferenceClassName() { |
| if ((referenceClassName == null) && (referenceClass != null)) { |
| referenceClassName = referenceClass.getName(); |
| } |
| return referenceClassName; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if partial attributes. |
| */ |
| public boolean hasPartialAttributeExpressions() { |
| return false; |
| } |
| |
| /** |
| * PUBLIC: |
| * Answers if the query lock mode is known to be LOCK or LOCK_NOWAIT. |
| * |
| * In the case of DEFAULT_LOCK_MODE and the query reference class being a CMP entity bean, |
| * at execution time LOCK, LOCK_NOWAIT, or NO_LOCK will be decided. |
| * <p> |
| * If a single joined attribute was configured for pessimistic locking then |
| * this will return true (after first execution) as the SQL contained a |
| * FOR UPDATE OF clause. |
| */ |
| public boolean isLockQuery() { |
| return getLockMode() > NO_LOCK; |
| } |
| |
| /** |
| * PUBLIC: |
| * Return if this is an object building query. |
| */ |
| @Override |
| public boolean isObjectBuildingQuery() { |
| return true; |
| } |
| |
| /** |
| * INTERNAL: |
| * Answers if we are executing through a UnitOfWork and registering results. |
| * This is only ever false if using the conforming without registering |
| * feature. |
| */ |
| public boolean isRegisteringResults() { |
| return ((shouldRegisterResultsInUnitOfWork() && this.descriptor.shouldRegisterResultsInUnitOfWork()) || isLockQuery()); |
| } |
| |
| /** |
| * PUBLIC: |
| * Refresh the attributes of the object(s) resulting from the query. |
| * If cascading is used the private parts of the objects will also be refreshed. |
| */ |
| public void refreshIdentityMapResult() { |
| setShouldRefreshIdentityMapResult(true); |
| } |
| |
| /** |
| * PUBLIC: |
| * Refresh the attributes of the object(s) resulting from the query. |
| * If cascading is used the private parts of the objects will also be refreshed. |
| */ |
| public void refreshRemoteIdentityMapResult() { |
| setShouldRefreshRemoteIdentityMapResult(true); |
| } |
| |
| /** |
| * INTERNAL: |
| * Constructs the final (registered) object for every individual object |
| * queried via a UnitOfWork. |
| * <p> |
| * Called for every object in a read all, the object in a read object, and |
| * every time the next or previous row is retrieved from a cursor. |
| * <p> |
| * The (conform) without registering feature is implemented here, and may |
| * return an original non UnitOfWork registered result. |
| * <p> |
| * Pessimistically locked objects are tracked here. |
| * |
| * @return a refreshed UnitOfWork queried object, unwrapped. |
| */ |
| public Object registerIndividualResult(Object result, Object primaryKey, UnitOfWorkImpl unitOfWork, JoinedAttributeManager joinManager, ClassDescriptor concreteDescriptor) { |
| if (concreteDescriptor == null) { |
| concreteDescriptor = unitOfWork.getDescriptor(result.getClass()); |
| } |
| // PERF: Do not register nor process read-only. |
| if (unitOfWork.isClassReadOnly(result.getClass(), concreteDescriptor)) { |
| // There is an obscure case where they object could be read-only and pessimistic. |
| // Record clone if referenced class has pessimistic locking policy. |
| recordCloneForPessimisticLocking(result, unitOfWork); |
| return result; |
| } |
| Object clone = null; |
| // For bug 2612601 Conforming without registering in Unit Of Work. |
| if (!isRegisteringResults()) { |
| if (primaryKey == null) { |
| primaryKey = concreteDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(result, getSession()); |
| } |
| clone = unitOfWork.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(primaryKey, result.getClass(), concreteDescriptor); |
| |
| // If object not registered do not register it here! Simply return |
| // the original to the user. |
| // Avoid setting clone = original, in case revert(clone) is called. |
| if (clone == null) { |
| clone = result; |
| } |
| } else { |
| // bug # 3183379 either the object comes from the shared cache and is existing, or |
| //it is from a parent unit of work and this unit of work does not need to know if it is new |
| //or not. It will query the parent unit of work to determine newness. |
| |
| clone = unitOfWork.registerExistingObject(result, concreteDescriptor, getQueryPrimaryKey(), true); |
| } |
| postRegisterIndividualResult(clone, result, primaryKey, unitOfWork, joinManager, concreteDescriptor); |
| return clone; |
| } |
| |
| /** |
| * Post process the object once it is registered in the unit of work. |
| */ |
| public void postRegisterIndividualResult(Object clone, Object original, Object primaryKey, UnitOfWorkImpl unitOfWork, JoinedAttributeManager joinManager, ClassDescriptor concreteDescriptor) { |
| // Check for refreshing, require to revert in the unit of work to accomplish a refresh. |
| if (shouldRefreshIdentityMapResult()) { |
| |
| if (shouldCascadeAllParts()) { |
| unitOfWork.mergeClone(original, MergeManager.CASCADE_ALL_PARTS, true); |
| } else if (shouldCascadePrivateParts()) { |
| unitOfWork.mergeClone(original, MergeManager.CASCADE_PRIVATE_PARTS, true); |
| } else if (shouldCascadeByMapping()) { |
| unitOfWork.mergeClone(original, MergeManager.CASCADE_BY_MAPPING, true); |
| } else if (!shouldCascadeParts()) { |
| unitOfWork.mergeClone(original, MergeManager.NO_CASCADE, true); |
| } |
| } |
| //bug 6130550: trigger indirection on the clone where required due to fetch joins on the query |
| if (joinManager != null && joinManager.hasJoinedAttributeExpressions()) { |
| triggerJoinExpressions(unitOfWork, joinManager, clone, concreteDescriptor); |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * Fetch/trigger indirection on the clone passed in, based on join expressions in the joinManager. |
| */ |
| private void triggerJoinExpressions(UnitOfWorkImpl unitOfWork, JoinedAttributeManager joinManager, Object clone, ClassDescriptor concreteDescriptor) { |
| List<Expression> joinExpressions = joinManager.getJoinedAttributeExpressions(); |
| int size = joinExpressions.size(); |
| if ((size == 0) || (clone == null)) { |
| return; |
| } |
| for (int index = 0; index < size; index++) {//since a's descriptor won't have a mapping for 'b'. |
| //baseExpression will be first relationship expression after the ExpressionBuilder, and may include aggregate intermediaries |
| QueryKeyExpression baseExpression = (QueryKeyExpression)joinManager.getJoinedAttributes().get(index); |
| DatabaseMapping mapping = joinManager.getJoinedAttributeMappings().get(index); |
| |
| if (mapping != null) { |
| Object attributeValue = joinManager.getValueFromObjectForExpression(unitOfWork, clone, baseExpression); |
| if (attributeValue != null) { |
| //recurse through the mapping if the expression's base isn't the base expressionBuilder |
| QueryKeyExpression queryKeyExpression = (QueryKeyExpression)joinExpressions.get(index); |
| if (baseExpression != queryKeyExpression) { |
| ObjectLevelReadQuery nestedQuery = null; |
| if (joinManager.getJoinedMappingQueryClones() == null) { |
| if (joinManager.getJoinedMappingQueries_() != null) { |
| nestedQuery = joinManager.getJoinedMappingQueries_().get(mapping); |
| } |
| } else { |
| nestedQuery = joinManager.getJoinedMappingQueryClones().get(mapping); |
| } |
| |
| //use the nestedQuery to trigger joins remaining for this expression (base onward) |
| if ((nestedQuery != null) && (nestedQuery.getJoinedAttributeManager() != null)) { |
| if (!mapping.isCollectionMapping()) { |
| triggerJoinExpressions(unitOfWork, nestedQuery.getJoinedAttributeManager(), attributeValue, null); |
| }else { |
| ContainerPolicy cp = mapping.getContainerPolicy(); |
| Object iterator = cp.iteratorFor(attributeValue); |
| while (cp.hasNext(iterator)){ |
| triggerJoinExpressions(unitOfWork, nestedQuery.getJoinedAttributeManager(), cp.next(iterator, unitOfWork), null); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * INTERNAL: |
| * When reading across relationships, queries may be set to acquire deferred locks |
| * This is used to ensure any Eagerly fetched object that is the target of a relationship |
| * with an object the acquires deferred locks behaves the same as its owner |
| */ |
| public boolean requiresDeferredLocks() { |
| return requiresDeferredLocks != null && requiresDeferredLocks; |
| } |
| |
| /** |
| * INTERNAL: |
| * Set the the time this query went to the database. |
| */ |
| public void setExecutionTime(long executionTime) { |
| this.executionTime = executionTime; |
| } |
| |
| /** |
| * PUBLIC: |
| * Sets whether this is a pessimistically locking query. |
| * <ul> |
| * <li>ObjectBuildingQuery.LOCK: SELECT .... FOR UPDATE issued. |
| * <li>ObjectBuildingQuery.LOCK_NOWAIT: SELECT .... FOR UPDATE NO WAIT issued. |
| * <li>ObjectBuildingQuery.NO_LOCK: no pessimistic locking. |
| * <li>ObjectBuildingQuery.DEFAULT_LOCK_MODE (default) and you have a CMP descriptor: |
| * fine grained locking will occur. |
| * </ul> |
| * <p>Fine Grained Locking: On execution the reference class |
| * and those of all joined attributes will be checked. If any of these have a |
| * PessimisticLockingPolicy set on their descriptor, they will be locked in a |
| * SELECT ... FOR UPDATE OF ... {NO WAIT}. Issues fewer locks |
| * and avoids setting the lock mode on each query. |
| * <p>Example:<code>readAllQuery.setSelectionCriteria(employee.get("address").equal("Ottawa"));</code> |
| * <ul><li>LOCK: all employees in Ottawa and all referenced Ottawa addresses will be locked. |
| * <li>DEFAULT_LOCK_MODE: if address is a joined attribute, and only address has a pessimistic |
| * locking policy, only referenced Ottawa addresses will be locked. |
| * </ul> |
| * @see org.eclipse.persistence.descriptors.PessimisticLockingPolicy |
| */ |
| public void setLockMode(short lockMode) { |
| lockingClause = ForUpdateClause.newInstance(lockMode); |
| } |
| |
| public void setPrefetchedCacheKeys(Map<Object, CacheKey> prefetchedCacheKeys) { |
| this.prefetchedCacheKeys = prefetchedCacheKeys; |
| } |
| |
| /** |
| * REQUIRED: |
| * Set the reference class for the query. |
| */ |
| public void setReferenceClass(Class<?> aClass) { |
| referenceClass = aClass; |
| setIsPrepared(false); |
| } |
| |
| /** |
| * INTERNAL: |
| * Set the reference class for the query. |
| */ |
| public void setReferenceClassName(String aClass) { |
| referenceClassName = aClass; |
| setIsPrepared(false); |
| } |
| |
| /** |
| * INTERNAL: |
| * When reading across relationships, queries may be set to acquire deferred locks |
| * This is used to ensure any Eagerly fetched object that is the target of a relationship |
| * with an object the acquires deferred locks behaves the same as its owner |
| */ |
| public void setRequiresDeferredLocks(boolean cascadeDeferredLocks) { |
| if (session != null && session.getProject().isQueryCacheForceDeferredLocks()) { |
| this.requiresDeferredLocks = true; |
| } else { |
| this.requiresDeferredLocks = cascadeDeferredLocks; |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Set if the attributes of the object(s) resulting from the query should be refreshed. |
| * If cascading is used the private parts of the objects will also be refreshed. |
| */ |
| public void setShouldRefreshIdentityMapResult(boolean shouldRefreshIdentityMapResult) { |
| this.shouldRefreshIdentityMapResult = shouldRefreshIdentityMapResult; |
| if (shouldRefreshIdentityMapResult) { |
| setShouldRefreshRemoteIdentityMapResult(true); |
| } |
| } |
| |
| /** |
| * PUBLIC: |
| * Set if the attributes of the object(s) resulting from the query should be refreshed. |
| * If cascading is used the private parts of the objects will also be refreshed. |
| */ |
| public void setShouldRefreshRemoteIdentityMapResult(boolean shouldRefreshIdentityMapResult) { |
| this.shouldRefreshRemoteIdentityMapResult = shouldRefreshIdentityMapResult; |
| } |
| |
| /** |
| * INTERNAL: |
| * Set to false to have queries conform to a UnitOfWork without registering |
| * any additional objects not already in that UnitOfWork. |
| * @see #shouldRegisterResultsInUnitOfWork |
| */ |
| public void setShouldRegisterResultsInUnitOfWork(boolean shouldRegisterResultsInUnitOfWork) { |
| // bug 2612601 |
| this.shouldRegisterResultsInUnitOfWork = shouldRegisterResultsInUnitOfWork; |
| } |
| |
| /** |
| * ADVANCED: |
| * If the user has isolated data and specified that the client session should |
| * use an exclusive connection then by setting this condition to true |
| * EclipseLink will ensure that the query is executed through the exclusive |
| * connection. This may be required in certain cases. An example being |
| * where database security will prevent a query joining to a secure table |
| * from returning the correct results when executed through the shared |
| * connection. |
| */ |
| public void setShouldUseExclusiveConnection(boolean shouldUseExclusiveConnection) { |
| this.shouldUseExclusiveConnection = shouldUseExclusiveConnection; |
| } |
| |
| /** |
| * INTERNAL: |
| * Allows one to do conforming in a UnitOfWork without registering. |
| * Queries executed on a UnitOfWork will only return working copies for objects |
| * that have already been registered. |
| * <p>Extreme care should be taken in using this feature, for a user will |
| * get back a mix of registered and original (unregistered) objects. |
| * <p>Best used with a WrapperPolicy where invoking on an object will trigger |
| * its registration (CMP). Without a WrapperPolicy {@link org.eclipse.persistence.sessions.UnitOfWork#registerExistingObject registerExistingObject} |
| * should be called on any object that you intend to change. |
| * @return true by default. |
| * @see #setShouldRegisterResultsInUnitOfWork |
| */ |
| public boolean shouldRegisterResultsInUnitOfWork() { |
| // bug 2612601 |
| return shouldRegisterResultsInUnitOfWork; |
| } |
| |
| /** |
| * ADVANCED: |
| * If the user has isolated data and specified that the client session should |
| * use an exclusive connection then by setting this condition to true |
| * EclipseLink will ensure that the query is executed through the exclusive |
| * connection. This may be required in certain cases. An example being |
| * where database security will prevent a query joining to a secure table |
| * from returning the correct results when executed through the shared |
| * connection. |
| */ |
| public boolean shouldUseExclusiveConnection() { |
| return this.shouldUseExclusiveConnection; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if this is a full object query, not partial nor fetch group. |
| */ |
| public boolean shouldReadAllMappings() { |
| return true; |
| } |
| |
| /** |
| * INTERNAL: |
| * Check if the mapping is part of the partial attributes. |
| */ |
| public boolean shouldReadMapping(DatabaseMapping mapping, FetchGroup fetchGroup) { |
| return true; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set to a boolean. When set means refresh the instance |
| * variables of referenceObject from the database. |
| */ |
| public boolean shouldRefreshIdentityMapResult() { |
| return shouldRefreshIdentityMapResult; |
| } |
| |
| /** |
| * PUBLIC: |
| * Set to a boolean. When set means refresh the instance |
| * variables of referenceObject from the database. |
| */ |
| public boolean shouldRefreshRemoteIdentityMapResult() { |
| return shouldRefreshRemoteIdentityMapResult; |
| } |
| |
| /** |
| * INTERNAL: |
| * Return if the attribute is specified for joining. |
| */ |
| public boolean isAttributeJoined(ClassDescriptor mappingDescriptor, String attributeName) { |
| return false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Returns true if an early return cache check was completed |
| */ |
| public boolean isCacheCheckComplete(){ |
| return this.isCacheCheckComplete; |
| } |
| |
| /** |
| * INTERNAL: |
| * Helper method that checks if clone has been locked with uow. |
| */ |
| public boolean isClonePessimisticLocked(Object clone, UnitOfWorkImpl uow) { |
| return false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Helper method that records clone with uow if query is pessimistic locking. |
| */ |
| public void recordCloneForPessimisticLocking(Object clone, UnitOfWorkImpl uow) { |
| if ((isLockQuery()) && lockingClause.isReferenceClassLocked()) { |
| uow.addPessimisticLockedClone(clone); |
| } |
| } |
| |
| /** |
| * INTERNAL: Helper method to determine the default mode. If true and quey has a pessimistic locking policy, |
| * locking will be configured according to the pessimistic locking policy. |
| */ |
| public boolean isDefaultLock() { |
| return (lockingClause == null); |
| } |
| |
| /** |
| * INTERNAL: |
| * If primary key is null ObjectBuilder.buildObject returns null |
| * in case this flag is set to true (instead of throwing exception). |
| */ |
| public boolean shouldBuildNullForNullPk() { |
| return shouldBuildNullForNullPk; |
| } |
| |
| /** |
| * INTERNAL: |
| * If primary key is null ObjectBuilder.buildObject returns null |
| * in case this flag is set to true (instead of throwing exception). |
| */ |
| public void setShouldBuildNullForNullPk(boolean shouldBuildNullForNullPk) { |
| this.shouldBuildNullForNullPk = shouldBuildNullForNullPk; |
| } |
| /** |
| * INTERNAL: |
| * Return if the query uses ResultSet optimization. |
| */ |
| public boolean usesResultSetAccessOptimization() { |
| return false; |
| } |
| |
| /** |
| * INTERNAL: |
| * Indicates whether the query should use SerializedObjectPolicy if descriptor has it. |
| */ |
| public boolean shouldUseSerializedObjectPolicy() { |
| return false; |
| } |
| } |