use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class ExpressionQueryMechanism method checkCacheForObject.
/**
* Perform a cache lookup for the query
* This is only called from read object query.
* The query has already checked that the cache should be checked.
*/
@Override
public Object checkCacheForObject(AbstractRecord translationRow, AbstractSession session) {
// For bug 2782991 a list of nearly 20 problems with this method have
// been fixed.
ReadObjectQuery query = getReadObjectQuery();
ClassDescriptor descriptor = getDescriptor();
boolean conforming = false;
UnitOfWorkImpl uow = null;
if (session.isUnitOfWork()) {
conforming = query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork();
uow = (UnitOfWorkImpl) session;
}
// Set the in memory query policy automatically for conforming queries, unless the
// user specifies the most cautious one.
int policyToUse = query.getInMemoryQueryIndirectionPolicyState();
if (conforming && (policyToUse != InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION)) {
// Bug 320764 - return not conformed by default, to avoid incorrect results being returned
policyToUse = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED;
}
Object cachedObject = null;
Expression selectionCriteria = getSelectionCriteria();
// Perform a series of cache checks, in the following order...
// 1: If selection key or selection object, lookup by primary key.
// 1.5: If row has sopObject, lookup by its primary key.
// 2: If selection criteria null, take the first instance in cache.
// 3: If exact primary key expression, lookup by primary key.
// 4: If inexact primary key expression, lookup by primary key and see if it conforms.
// 5: Perform a linear search on the cache, calling doesConform on each object.
// 6: (Conforming) Search through new objects.
// Each check is more optimal than the next.
// Finally: (Conforming) check that any positive result was not deleted in the UnitOfWork.
// 1: If selection key or selection object, do lookup by primary key.
Object selectionKey = query.getSelectionId();
Object selectionObject = query.getSelectionObject();
if ((selectionKey != null) || (selectionObject != null)) {
if (selectionKey == null) {
selectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(selectionObject, session, true);
if (selectionKey == null) {
// Has a null primary key, so must not exist.
return InvalidObject.instance;
}
// Must be checked separately as the expression and row is not yet set.
query.setSelectionId(selectionKey);
}
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
}
} else {
//
if (translationRow != null && translationRow.hasSopObject()) {
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(translationRow.getSopObject(), session), query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(translationRow.getSopObject(), session), query.getReferenceClass(), false, descriptor);
}
} else {
//
if (selectionCriteria == null) {
// In future would like to always return something from cache.
if (query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork() || query.shouldCheckCacheOnly() || query.shouldCheckCacheThenDatabase()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(null, query.getReferenceClass(), translationRow, policyToUse, conforming, false, descriptor);
}
} else {
// 3: If can extract exact primary key expression, do lookup by primary key.
//
selectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(true, selectionCriteria, translationRow, session);
// primary key only this will become the final check.
if ((selectionKey != null) || query.shouldCheckCacheByExactPrimaryKey()) {
if (selectionKey != null) {
// Check if key is invalid (null), cannot exist.
if (selectionKey == InvalidObject.instance) {
return selectionKey;
}
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(selectionKey, query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(selectionKey, query.getReferenceClass(), false, descriptor);
}
// Because it was exact primary key if the lookup failed then it is not there.
}
} else {
// 4: If can extract inexact primary key, find one object by primary key and
// check if it conforms. Failure of this object to conform however does not
// rule out a cache hit.
// Check for any primary key in expression, may have other stuff.
Object inexactSelectionKey = descriptor.getObjectBuilder().extractPrimaryKeyFromExpression(false, selectionCriteria, translationRow, session);
if (inexactSelectionKey != null) {
// Check if key is invalid (null), cannot exist.
if (selectionKey == InvalidObject.instance) {
return selectionKey;
}
// PERF: Only use deferred lock when required.
if (query.requiresDeferredLocks()) {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMapWithDeferredLock(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
} else {
cachedObject = session.getIdentityMapAccessorInstance().getFromLocalIdentityMap(inexactSelectionKey, query.getReferenceClass(), false, descriptor);
}
} else {
CacheKey cacheKey = descriptor.getCachePolicy().checkCacheByIndex(selectionCriteria, translationRow, descriptor, session);
if (cacheKey != null) {
if (query.requiresDeferredLocks()) {
cacheKey.checkDeferredLock();
} else {
cacheKey.checkReadLock();
}
cachedObject = cacheKey.getObject();
}
}
if (cachedObject != null) {
// Must ensure that it matches the expression.
try {
// PERF: 3639015 - cloning the expression no longer required
// when using the root session.
ExpressionBuilder builder = selectionCriteria.getBuilder();
builder.setSession(session.getRootSession(null));
builder.setQueryClass(descriptor.getJavaClass());
if (!selectionCriteria.doesConform(cachedObject, session, translationRow, policyToUse)) {
cachedObject = null;
}
} catch (QueryException exception) {
// Ignore if expression too complex.
if (query.shouldCheckCacheOnly()) {
// Throw on only cache.
throw exception;
}
cachedObject = null;
}
}
// 5: Perform a linear search of the cache, calling expression.doesConform on each element.
// This is a last resort linear time search of the identity map.
// This can be avoided by setting check cache by (inexact/exact) primary key on the query.
// That flag becomes invalid in the conforming case (bug 2609611: SUPPORT CONFORM RESULT IN UOW IN CONJUNCTION WITH OTHER IN-MEMORY FEATURES)
// so if conforming must always do this linear search, but at least only on
// objects registered in the UnitOfWork.
//
boolean conformingButOutsideUnitOfWork = ((query.shouldConformResultsInUnitOfWork() || descriptor.shouldAlwaysConformResultsInUnitOfWork()) && !session.isUnitOfWork());
if ((cachedObject == null) && (conforming || (!query.shouldCheckCacheByPrimaryKey() && !conformingButOutsideUnitOfWork))) {
// when using the root session
if (selectionCriteria != null) {
ExpressionBuilder builder = selectionCriteria.getBuilder();
builder.setSession(session.getRootSession(null));
builder.setQueryClass(descriptor.getJavaClass());
}
try {
cachedObject = session.getIdentityMapAccessorInstance().getFromIdentityMap(selectionCriteria, query.getReferenceClass(), translationRow, policyToUse, conforming, false, descriptor);
} catch (QueryException exception) {
// Ignore if expression too complex.
if (query.shouldCheckCacheOnly()) {
// Throw on only cache.
throw exception;
}
}
}
}
}
}
}
//
if (conforming) {
if (cachedObject == null) {
if (selectionKey != null) {
cachedObject = uow.getObjectFromNewObjects(query.getReferenceClass(), selectionKey);
} else {
// when using the root session
if (selectionCriteria != null) {
ExpressionBuilder builder = selectionCriteria.getBuilder();
builder.setSession(session.getRootSession(null));
builder.setQueryClass(descriptor.getJavaClass());
}
try {
cachedObject = uow.getObjectFromNewObjects(selectionCriteria, query.getReferenceClass(), translationRow, policyToUse);
} catch (QueryException exception) {
// Ignore if expression too complex.
}
}
}
//
if (cachedObject != null) {
if (uow.isObjectDeleted(cachedObject)) {
if (selectionKey != null) {
// that the object was found but null must be returned.
return InvalidObject.instance;
} else {
cachedObject = null;
}
}
}
}
if (cachedObject != null) {
// Fetch group check, ensure object is fetched.
if (descriptor.hasFetchGroupManager()) {
if (descriptor.getFetchGroupManager().isPartialObject(cachedObject)) {
FetchGroup fetchGroup = query.getExecutionFetchGroup(descriptor);
EntityFetchGroup entityFetchGroup = null;
if (fetchGroup != null) {
entityFetchGroup = descriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup);
}
if (!descriptor.getFetchGroupManager().isObjectValidForFetchGroup(cachedObject, entityFetchGroup)) {
// the cached object is partially fetched, and it's fetch group is not a superset of the one in the query, so the cached object is not valid for the query.
cachedObject = null;
}
}
}
}
// in which case the parent cache still needs to be checked.
if ((cachedObject == null) && query.shouldCheckCacheOnly() && ((uow == null) || (!uow.isNestedUnitOfWork() && descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork()))) {
return InvalidObject.instance;
}
return cachedObject;
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class MapContainerPolicy method addNextValueFromIteratorInto.
/**
* INTERNAL:
* This method is used to add the next value from an iterator built using ContainerPolicy's iteratorFor() method
* into the toCollection. Since this ContainerPolicy represents a Map, the key and the value are extracted and added.
*/
@Override
public void addNextValueFromIteratorInto(Object valuesIterator, Object parent, CacheKey parentCacheKey, Object toCollection, CollectionMapping mapping, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache) {
Map.Entry entry = ((MapContainerPolicyIterator) valuesIterator).next();
Object clonedKey = buildCloneForKey(entry.getKey(), parent, parentCacheKey, refreshCascade, cloningSession, isExisting, isFromSharedCache);
Object clonedValue = buildCloneForValue(entry.getValue(), parent, parentCacheKey, mapping, refreshCascade, cloningSession, isExisting, isFromSharedCache);
// uow should discover new objects
if (cloningSession.isUnitOfWork() && mapping.isCandidateForPrivateOwnedRemoval() && ((UnitOfWorkImpl) cloningSession).shouldDiscoverNewObjects()) {
if (clonedValue != null && ((UnitOfWorkImpl) cloningSession).isCloneNewObject(clonedValue)) {
((UnitOfWorkImpl) cloningSession).addPrivateOwnedObject(mapping, clonedValue);
}
}
addInto(clonedKey, clonedValue, toCollection, cloningSession);
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class ExpressionBuilderTestSuite method testUnitOfWorkInExpressionBuilder.
// Bug# 429232 - Instance of UnitOfWork is stored in ExpressionBuilder inside ConcurrentFixedCache
// Make sure that [ExpressionBuilder].setSession() will not store UnitOfWork inside builder even
// when UnitOfWork is passed as an argument.
public void testUnitOfWorkInExpressionBuilder() {
ExpressionBuilder builder = new ExpressionBuilder();
UnitOfWorkImpl uow = (UnitOfWorkImpl) getSession().acquireUnitOfWork();
builder.setSession(uow);
AbstractSession session = builder.getSession();
if (session instanceof UnitOfWork) {
throw new TestErrorException("Session stored in ExpressionBuilder shall not be UnitOfWork.");
}
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class ReadOnlyClassAccessingTestCase method test.
@Override
protected void test() {
// Test acquiring a unit of work.
UnitOfWork uow1 = getSession().acquireUnitOfWork();
if (!uow1.getReadOnlyClasses().isEmpty()) {
throw new TestErrorException(" When acquiring a UnitOfWork from a Session, the read-only classes where not empty as expected.");
}
uow1.release();
// Test acquiring a unit of work with a vector of read-only classes.
Vector classes = new Vector();
classes.addElement(Promoter.class);
classes.addElement(Country.class);
UnitOfWork uow2 = getSession().acquireUnitOfWork();
uow2.removeAllReadOnlyClasses();
uow2.addReadOnlyClasses(classes);
if (!areEqual(uow2.getReadOnlyClasses(), classes)) {
throw new TestErrorException("When acquiring a UnitOfWork from a Session, the read-only classes specified did not get set in the UnitOfWork;");
}
// Test the testing of read-only classes
for (Enumeration enumtr = classes.elements(); enumtr.hasMoreElements(); ) {
if (!uow2.isClassReadOnly((Class) enumtr.nextElement())) {
throw new TestErrorException("Testing whether a class is read-only or not has failed.");
}
}
if (uow2.isClassReadOnly(Vector.class)) {
throw new TestErrorException("Testing whether a class is read-only or not has failed.");
}
// Test the add and remove of read-only classes.
uow2.removeReadOnlyClass(Promoter.class);
if (uow2.isClassReadOnly(Promoter.class)) {
throw new TestErrorException("The method removeReadOnlyClass(Class) failed.");
}
uow2.addReadOnlyClass(Promoter.class);
if (!uow2.isClassReadOnly(Promoter.class)) {
throw new TestErrorException("The method addReadOnlyClass(Class) failed.");
}
// Test the removeAll.
uow2.removeAllReadOnlyClasses();
if ((uow2.isClassReadOnly(Country.class)) || (!uow2.getReadOnlyClasses().isEmpty())) {
throw new TestErrorException("Did not remove all the read-only classes from a UnitOfWork properly");
}
// Check that we cannot make changes to the read-only set after registering an object.
try {
uow2.registerObject(new Address());
uow2.removeAllReadOnlyClasses();
uow2.addReadOnlyClasses(classes);
if (areEqual(uow2.getReadOnlyClasses(), classes)) {
throw new TestErrorException("Shouldn't be able to change the readOnlyClasses of a UnitOfWork after an object was registered.");
}
} catch (org.eclipse.persistence.exceptions.ValidationException ex) {
getSession().logMessage("Caught validation exeception...OK");
} finally {
uow2.release();
}
// Check that the default read-only classes work.
Vector someClasses = new Vector();
someClasses.addElement(Country.class);
someClasses.addElement(Address.class);
getSession().getProject().setDefaultReadOnlyClasses(someClasses);
UnitOfWork uow3 = getSession().acquireUnitOfWork();
if (!areEqual(uow3.getReadOnlyClasses(), someClasses)) {
throw new TestErrorException("The default read-only classes were not set properly when a UnitOfWork was aquired");
}
// Nested units of work should not be able to reduce the set of read-only classes.
UnitOfWork uow4 = uow3.acquireUnitOfWork();
try {
uow4.removeAllReadOnlyClasses();
} catch (org.eclipse.persistence.exceptions.ValidationException ex) {
getSession().logMessage("Check the nested units of work read-only classes. OK");
} finally {
uow3.release();
uow4.release();
}
// You should be able to get the default set of read-only classes from nested UnitOfWork objects.
UnitOfWork uow5 = getSession().acquireUnitOfWork();
UnitOfWork uow6 = uow5.acquireUnitOfWork();
if (!areEqual(((UnitOfWorkImpl) uow5).getDefaultReadOnlyClasses(), ((UnitOfWorkImpl) uow6).getDefaultReadOnlyClasses()))
throw new TestErrorException("Nested UnitOfWorks did not return consistent default read-only classes.");
uow5.release();
uow6.release();
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class UnitOfWorkExistingObjectsListTest method test.
@Override
public void test() {
Session session = getSession();
UnitOfWork uow = session.acquireUnitOfWork();
Address addr = (Address) uow.readObject(Address.class);
uow.release();
uow = session.acquireUnitOfWork();
uow.setValidationLevel(UnitOfWorkImpl.None);
Employee emp = new Employee();
uow.registerNewObject(emp);
emp.setAddress(addr);
uow.assignSequenceNumbers();
if (!((UnitOfWorkImpl) uow).getUnregisteredExistingObjects().containsKey(addr)) {
throw new TestErrorException(" Bug 294259 - Duplicate existence checks in same UOW. Patch Failed");
}
uow.release();
}
Aggregations