use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class ObjectLevelReadQuery method checkEarlyReturn.
/**
* INTERNAL:
* Check to see if this query already knows the return value without performing any further work.
*/
@Override
public Object checkEarlyReturn(AbstractSession session, AbstractRecord translationRow) {
// For bug 3136413/2610803 building the selection criteria from an EJBQL string or
// an example object is done just in time.
// Also calls checkDescriptor here.
// buildSelectionCriteria(session);
checkPrePrepare(session);
if (!session.isUnitOfWork()) {
return checkEarlyReturnLocal(session, translationRow);
}
UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl) session;
// The cache check must happen on the UnitOfWork in these cases either
// to access transient state or for pessimistic locking, as only the
// UOW knows which objects it has locked.
Object result = null;
// PERF: Avoid uow check for read-only.
if (!this.descriptor.shouldBeReadOnly()) {
result = checkEarlyReturnLocal(unitOfWork, translationRow);
}
if (result != null) {
return result;
}
// An error should be thrown on prepare is checkCacheOnly is used with these.
if ((!unitOfWork.isNestedUnitOfWork()) && (this.descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork() || isLockQuery()) || unitOfWork.shouldForceReadFromDB(this, null)) {
return null;
}
// follow the execution path in looking for the object.
AbstractSession parentSession = unitOfWork.getParentIdentityMapSession(this);
// assert parentSession != unitOfWork;
result = checkEarlyReturn(parentSession, translationRow);
if (result != null) {
// treat this as cache hit but return null. Bug 2782991.
if (result == InvalidObject.instance) {
return result;
}
Object clone = registerResultInUnitOfWork(result, unitOfWork, translationRow, false);
if (shouldConformResultsInUnitOfWork() && unitOfWork.isObjectDeleted(clone)) {
return InvalidObject.instance;
}
return clone;
} else {
return null;
}
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class DeleteAllQuery method executeDatabaseQuery.
/**
* INTERNAL:
* Perform the work to delete a collection of objects.
* This skips the optimistic lock check and should not called for objects using locking.
* @exception DatabaseException - an error has occurred on the database.
* @return Integer the number of objects (rows) deleted.
*/
@Override
public Object executeDatabaseQuery() throws DatabaseException {
// CR# 4286
if (this.objects != null) {
if (isExpressionQuery() && getSelectionCriteria() == null) {
// DeleteAllQuery has objects so it *must* have selectionCriteria, too
throw QueryException.deleteAllQuerySpecifiesObjectsButNotSelectionCriteria(getDescriptor(), this, this.objects.toString());
}
// Optimistic lock check not required because objects are deleted individually in that case.
try {
this.session.beginTransaction();
// PERF: Avoid events if no listeners.
if (this.descriptor.getEventManager().hasAnyEventListeners()) {
for (Object object : this.objects) {
DescriptorEvent event = new DescriptorEvent(object);
event.setEventCode(DescriptorEventManager.PreDeleteEvent);
event.setSession(this.session);
event.setQuery(this);
this.descriptor.getEventManager().executeEvent(event);
}
}
if (this.isInMemoryOnly) {
result = 0;
} else {
result = this.queryMechanism.deleteAll();
}
// PERF: Avoid events if no listeners.
if (this.descriptor.getEventManager().hasAnyEventListeners()) {
for (Object object : this.objects) {
DescriptorEvent event = new DescriptorEvent(object);
event.setEventCode(DescriptorEventManager.PostDeleteEvent);
event.setSession(this.session);
event.setQuery(this);
this.descriptor.getEventManager().executeEvent(event);
}
}
if (shouldMaintainCache()) {
// remove from the cache.
for (Object deleted : this.objects) {
if (this.session.isUnitOfWork()) {
// BUG #2612169: Unwrap is needed
deleted = this.descriptor.getObjectBuilder().unwrapObject(deleted, getSession());
((UnitOfWorkImpl) this.session).addObjectDeletedDuringCommit(deleted, this.descriptor);
} else {
this.session.getIdentityMapAccessor().removeFromIdentityMap(deleted);
}
}
}
this.session.commitTransaction();
} catch (RuntimeException exception) {
this.session.rollbackTransaction();
throw exception;
}
} else {
if (this.isInMemoryOnly) {
result = 0;
} else {
// fire the SQL to the database
result = this.queryMechanism.deleteAll();
}
mergeChangesIntoSharedCache();
}
return result;
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class DeleteObjectQuery method executeDatabaseQuery.
/**
* INTERNAL:
* Perform the work to delete an object.
* @return object - the object being deleted.
*/
@Override
public Object executeDatabaseQuery() throws DatabaseException, OptimisticLockException {
AbstractSession session = getSession();
CommitManager commitManager = session.getCommitManager();
Object object = getObject();
boolean isUnitOfWork = session.isUnitOfWork();
try {
// Check if the object has already been deleted, then no work is required.
if (commitManager.isCommitCompletedInPostOrIgnore(object)) {
return object;
}
ClassDescriptor descriptor = this.descriptor;
// if it is, then there is a cycle, and the foreign keys must be nulled.
if (commitManager.isCommitInPreModify(object)) {
if (!commitManager.isShallowCommitted(object)) {
getQueryMechanism().updateForeignKeyFieldBeforeDelete();
if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
descriptor.getHistoryPolicy().postUpdate(this);
}
commitManager.markShallowCommit(object);
}
return object;
}
commitManager.markPreModifyCommitInProgress(getObject());
if (!isUnitOfWork) {
session.beginTransaction();
}
DescriptorEventManager eventManager = descriptor.getEventManager();
// PERF: Avoid events if no listeners.
if (eventManager.hasAnyEventListeners()) {
// Need to run pre-delete selector if available
eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PreDeleteEvent, this));
}
// Verify if deep shallow modify is turned on
if (shouldCascadeParts()) {
descriptor.getQueryManager().preDelete(this);
}
// Check for deletion dependencies.
if (isUnitOfWork) {
Set<Object> dependencies = ((UnitOfWorkImpl) session).getDeletionDependencies(object);
if (dependencies != null) {
for (Object dependency : dependencies) {
if (!commitManager.isCommitCompletedInPostOrIgnore(dependency)) {
ClassDescriptor dependencyDescriptor = session.getDescriptor(dependency);
// PERF: Get the descriptor query, to avoid extra query creation.
DeleteObjectQuery deleteQuery = dependencyDescriptor.getQueryManager().getDeleteQuery();
if (deleteQuery == null) {
deleteQuery = new DeleteObjectQuery();
deleteQuery.setDescriptor(dependencyDescriptor);
} else {
// Ensure original query has been prepared.
deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow());
deleteQuery = (DeleteObjectQuery) deleteQuery.clone();
}
deleteQuery.setIsExecutionClone(true);
deleteQuery.setObject(dependency);
session.executeQuery(deleteQuery);
}
}
}
}
// PERF: Avoid events if no listeners.
if (eventManager.hasAnyEventListeners()) {
DescriptorEvent event = new DescriptorEvent(DescriptorEventManager.AboutToDeleteEvent, this);
event.setRecord(getModifyRow());
eventManager.executeEvent(event);
}
if (QueryMonitor.shouldMonitor()) {
QueryMonitor.incrementDelete(this);
}
int rowCount = 0;
// If the object was/will be deleted from a cascade delete constraint, ignore it.
if (isUnitOfWork && ((UnitOfWorkImpl) session).hasCascadeDeleteObjects() && ((UnitOfWorkImpl) session).getCascadeDeleteObjects().contains(object)) {
// Cascade delete does not check optimistic lock, assume ok.
rowCount = 1;
} else {
rowCount = getQueryMechanism().deleteObject();
}
if (rowCount < 1) {
if (session.hasEventManager()) {
session.getEventManager().noRowsModified(this, object);
}
}
if (this.usesOptimisticLocking) {
descriptor.getOptimisticLockingPolicy().validateDelete(rowCount, object, this);
}
commitManager.markPostModifyCommitInProgress(getObject());
// Verify if deep shallow modify is turned on
if (shouldCascadeParts()) {
descriptor.getQueryManager().postDelete(this);
}
if ((descriptor.getHistoryPolicy() != null) && descriptor.getHistoryPolicy().shouldHandleWrites()) {
descriptor.getHistoryPolicy().postDelete(this);
}
// PERF: Avoid events if no listeners.
if (eventManager.hasAnyEventListeners()) {
// Need to run post-delete selector if available
eventManager.executeEvent(new DescriptorEvent(DescriptorEventManager.PostDeleteEvent, this));
}
if (!isUnitOfWork) {
session.commitTransaction();
}
commitManager.markCommitCompleted(object);
// CR3510313, avoid removing aggregate collections from cache (maintain cache is false).
if (shouldMaintainCache()) {
if (isUnitOfWork) {
((UnitOfWorkImpl) session).addObjectDeletedDuringCommit(object, descriptor);
} else {
session.getIdentityMapAccessorInstance().removeFromIdentityMap(getPrimaryKey(), descriptor.getJavaClass(), descriptor, object);
}
}
return object;
} catch (RuntimeException exception) {
if (!isUnitOfWork) {
session.rollbackTransaction();
}
commitManager.markCommitCompleted(object);
throw exception;
}
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class DoesExistQuery method checkEarlyReturn.
/**
* INTERNAL:
* Check if existence can be determined without going to the database.
* Note that custom query check is not require for does exist as the custom is always used.
* Used by unit of work, and will return null if checkDatabaseIfInvalid is set and the cachekey is invalidated
*/
public Object checkEarlyReturn(Object object, Object primaryKey, AbstractSession session, AbstractRecord translationRow) {
// For bug 3136413/2610803 building the selection criteria from an EJBQL string or
// an example object is done just in time.
buildSelectionCriteria(session);
// Return false on null since it can't exist. Little more done in case PK not set in the query
if (object == null) {
return Boolean.FALSE;
}
ClassDescriptor descriptor = session.getDescriptor(object.getClass());
if (primaryKey == null) {
primaryKey = getPrimaryKey();
if (primaryKey == null) {
primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session, true);
}
}
if (primaryKey == null) {
return Boolean.FALSE;
}
// Need to do the cache check first if flag set or if we should check the cache only for existence.
if ((shouldCheckCacheForDoesExist() || this.checkCacheFirst) && !descriptor.isDescriptorForInterface()) {
// If this is a UOW and modification queries have been executed, the cache cannot be trusted.
if (this.checkDatabaseIfInvalid && (session.isUnitOfWork() && ((UnitOfWorkImpl) session).shouldReadFromDB())) {
return null;
}
CacheKey cacheKey;
Class<?> objectClass = object.getClass();
AbstractSession tempSession = session;
if (tempSession.isUnitOfWork()) {
cacheKey = tempSession.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, objectClass, descriptor);
if (cacheKey != null) {
// If in the UOW cache it can't be invalid.
return Boolean.TRUE;
}
while (((UnitOfWorkImpl) tempSession).isNestedUnitOfWork()) {
// could be nested lets check all UOWs
tempSession = tempSession.getParent();
cacheKey = tempSession.getIdentityMapAccessorInstance().getCacheKeyForObjectForLock(primaryKey, objectClass, descriptor);
if (cacheKey != null) {
// If in the UOW cache it can't be invalid.
return Boolean.TRUE;
}
}
tempSession = tempSession.getParentIdentityMapSession(descriptor, false, true);
}
// Did not find it registered in UOW so check main cache and check for invalidation.
cacheKey = tempSession.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, objectClass, descriptor, false);
if ((cacheKey != null)) {
// Assume that if there is a cachekey, object exists.
if (this.checkDatabaseIfInvalid) {
checkDescriptor(object, session);
if (this.descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey, System.currentTimeMillis())) {
return null;
}
}
Object objectFromCache = cacheKey.getObject();
if ((session.isUnitOfWork()) && ((UnitOfWorkImpl) session).wasDeleted(objectFromCache)) {
if (shouldCheckCacheForDoesExist()) {
return Boolean.FALSE;
}
} else {
return Boolean.TRUE;
}
} else if (shouldCheckCacheForDoesExist()) {
// We know its not in cache, and a checkcache policy so return false.
return Boolean.FALSE;
}
}
// Check if we have to assume that the object does not exist.
if (shouldAssumeNonExistenceForDoesExist()) {
return Boolean.FALSE;
}
// Check to see if we only need to check that the object contains a primary key.
if (shouldAssumeExistenceForDoesExist()) {
return Boolean.TRUE;
}
return null;
}
use of org.eclipse.persistence.internal.sessions.UnitOfWorkImpl in project eclipselink by eclipse-ee4j.
the class LifecycleJUnitTest method testClearWhileEntityManagerInCommitPendingStateWithClearAfterCommit.
/**
* This test simulates EE container callbacks that could occur that affect em lifecycle state.
* Specifically it tests whether we handle an attempt to clear an entityManager
* that is in the middle of a commit.
* We only clear the entityManager if we are in the states
* (Birth == 0, WriteChangesFailed==3, Death==5 or AfterExternalTransactionRolledBack==6).
* If we are in one of the following *Pending states we defer the clear() to the release() call later
*/
public void testClearWhileEntityManagerInCommitPendingStateWithClearAfterCommit() {
EntityManagerFactory emf = getEntityManagerFactory();
EntityManager em = emf.createEntityManager();
Department dept = null;
try {
em.getTransaction().begin();
dept = new Department();
// A merge will not populate the @Id field
// A persist will populate the @Id field
em.persist(dept);
// simulate an attempt to call close() while we are in the middle of a commit
UnitOfWorkImpl uow = getUnitOfWorkFromEntityManager(em);
// get lifecycle state
int lifecycleBefore = uow.getLifecycle();
assertEquals("Birth state 0 is not set ", 0, lifecycleBefore);
em.clear();
int lifecycleAfter = uow.getLifecycle();
assertEquals("Birth state 0 is not set after a clear on state Birth ", 0, lifecycleAfter);
em.getTransaction().commit();
// clear em
em.clear();
int lifecycleAfterCommit = uow.getLifecycle();
assertEquals("Birth state 0 is not set after commit ", 0, lifecycleAfterCommit);
} catch (RuntimeException ex) {
if (isTransactionActive(em)) {
rollbackTransaction(em);
}
closeEntityManager(em);
throw ex;
} finally {
closeEntityManager(em);
}
}
Aggregations