OPENJPA-610: Restored refresh() behavior for clean/new instances.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@667312 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2008-06-13 01:58:49 +00:00
parent 514a4bb907
commit 71519b0808
2 changed files with 124 additions and 57 deletions

View File

@ -2733,7 +2733,7 @@ public class BrokerImpl
endOperation();
}
}
public void refreshAll(Collection objs, OpCallbacks call) {
if (objs == null || objs.isEmpty())
return;
@ -2742,10 +2742,14 @@ public class BrokerImpl
try {
assertNontransactionalRead();
for (Iterator itr = objs.iterator(); itr.hasNext();) {
for (Iterator itr = objs.iterator(); itr.hasNext();)
gatherCascadeRefresh(itr.next(), call);
}
refreshInternal(_operating, call);
if (_operating.isEmpty())
return;
if (_operating.size() == 1)
refreshInternal(_operating.iterator().next(), call);
else
refreshInternal(_operating, call);
} finally {
endOperation();
}
@ -2760,7 +2764,12 @@ public class BrokerImpl
assertNontransactionalRead();
gatherCascadeRefresh(obj, call);
refreshInternal(_operating, call);
if (_operating.isEmpty())
return;
if (_operating.size() == 1)
refreshInternal(_operating.iterator().next(), call);
else
refreshInternal(_operating, call);
} finally {
endOperation();
}
@ -2797,7 +2806,7 @@ public class BrokerImpl
List exceps = null;
try {
// collect instances that need a refresh
Collection load = new ArrayList(objs.size());
Collection load = null;
StateManagerImpl sm;
Object obj;
for (Iterator itr = objs.iterator(); itr.hasNext();) {
@ -2812,9 +2821,11 @@ public class BrokerImpl
continue;
if (sm != null) {
if (sm.isDetached()) {
if (sm.isDetached())
throw newDetachedException(obj, "refresh");
} else if (sm.beforeRefresh(true)) {
else if (sm.beforeRefresh(true)) {
if (load == null)
load = new ArrayList(objs.size());
load.add(sm);
}
} else if (assertPersistenceCapable(obj).pcIsDetached()
@ -2826,7 +2837,7 @@ public class BrokerImpl
}
// refresh all
if (!load.isEmpty()) {
if (load != null) {
Collection failed = _store.loadAll(load, null,
StoreManager.FORCE_LOAD_REFRESH, _fc, null);
if (failed != null && !failed.isEmpty())
@ -2868,6 +2879,36 @@ public class BrokerImpl
throwNestedExceptions(exceps, false);
}
/**
* Optimization for single-object refresh.
*/
protected void refreshInternal(Object obj, OpCallbacks call) {
try {
StateManagerImpl sm = getStateManagerImpl(obj, true);
if ((processArgument(OpCallbacks.OP_REFRESH, obj, sm, call)
& OpCallbacks.ACT_RUN) == 0)
return;
if (sm != null) {
if (sm.isDetached())
throw newDetachedException(obj, "refresh");
else if (sm.beforeRefresh(false)) {
sm.load(_fc, StateManagerImpl.LOAD_FGS, null, null, false);
sm.afterRefresh();
}
fireLifecycleEvent(sm.getManagedInstance(), null,
sm.getMetaData(), LifecycleEvent.AFTER_REFRESH);
} else if (assertPersistenceCapable(obj).pcIsDetached()
== Boolean.TRUE)
throw newDetachedException(obj, "refresh");
} catch (OpenJPAException ke) {
throw ke;
} catch (RuntimeException re) {
throw new GeneralException(re);
}
}
public void retrieveAll(Collection objs, boolean dfgOnly,
OpCallbacks call) {
if (objs == null || objs.isEmpty())

View File

@ -19,10 +19,10 @@
package org.apache.openjpa.persistence.datacache;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.LockModeType;
import org.apache.openjpa.persistence.EntityManagerImpl;
import org.apache.openjpa.persistence.EntityNotFoundException;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
import org.apache.openjpa.persistence.StoreCache;
@ -54,7 +54,10 @@ public class TestDataCacheBehavesIdentical extends AbstractTestCase {
private static final boolean WITH_DATACACHE = true;
private static final boolean CONSISTENT = true;
private static final boolean DIRTY = true;
private static final boolean REFRESH_FROM_DATACACHE = true;
private static final LockModeType NOLOCK = null;
private static final Class ENTITY_NOT_FOUND_ERROR = EntityNotFoundException.class;
private static final Class NO_ERROR = null;
private static final String MARKER_DATACACHE = "in DataCache";
private static final String MARKER_DATABASE = "in Database";
@ -356,68 +359,66 @@ public class TestDataCacheBehavesIdentical extends AbstractTestCase {
String getExpectedMarker(boolean useDataCache, LockModeType lock,
boolean makeDirtyBeforeRefresh) {
if (useDataCache) {
// return (lock != null && makeDirtyBeforeRefresh)
return (lock != null) ? MARKER_DATABASE : MARKER_DATACACHE;
} else {
// return (makeDirtyBeforeRefresh) ? MARKER_DATABASE : MARKER_CACHE;
return MARKER_DATABASE;
}
}
public void testDirtyRefreshWithNoLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, NOLOCK, DIRTY, false, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, NOLOCK, DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
}
public void testDirtyRefreshWithNoLockHitsDataCache() {
verifyRefresh(WITH_DATACACHE, NOLOCK, DIRTY, true, MARKER_DATACACHE);
verifyRefresh(WITH_DATACACHE, NOLOCK, DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
}
public void testCleanRefreshWithNoLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, NOLOCK, !DIRTY, false, MARKER_DATABASE);
public void testCleanRefreshWithNoLockDoesNotHitDatabase() {
verifyRefresh(WITH_DATACACHE, NOLOCK, !DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
}
public void testCleanRefreshWithNoLockHitsDataCache() {
verifyRefresh(WITH_DATACACHE, NOLOCK, !DIRTY, true, MARKER_DATACACHE);
verifyRefresh(WITH_DATACACHE, NOLOCK, !DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
}
public void testDirtyRefreshWithReadLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, LockModeType.READ, DIRTY, true, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.READ, DIRTY, false, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.READ, DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.READ, DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATABASE);
}
public void testCleanRefreshWithReadLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, LockModeType.READ, !DIRTY, true, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.READ, !DIRTY, false, MARKER_DATABASE);
public void testCleanRefreshWithReadLockDoesNotHitDatabase() {
verifyRefresh(WITH_DATACACHE, LockModeType.READ, !DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
verifyRefresh(WITH_DATACACHE, LockModeType.READ, !DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
}
public void testDirtyRefreshWithWriteLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, DIRTY, true, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, DIRTY, false, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATABASE);
}
public void testCleanRefreshWithWriteLockHitsDatabase() {
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, !DIRTY, true, MARKER_DATABASE);
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, !DIRTY, false, MARKER_DATABASE);
public void testCleanRefreshWithWriteLockDoesNotHitDatabase() {
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, !DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
verifyRefresh(WITH_DATACACHE, LockModeType.WRITE, !DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATACACHE);
}
public void testDirtyRefreshWithoutDataCacheAlwaysHitsDatabase() {
verifyRefresh(!WITH_DATACACHE, NOLOCK, DIRTY, true, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, DIRTY, true, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, DIRTY, true, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, NOLOCK, DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, DIRTY, REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, NOLOCK, DIRTY, false, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, DIRTY, false, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, DIRTY, false, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, NOLOCK, DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, DIRTY, !REFRESH_FROM_DATACACHE, MARKER_DATABASE);
}
public void testCleanRefreshWithoutDataCacheAlwaysHitsDatabase() {
verifyRefresh(!WITH_DATACACHE, NOLOCK, !DIRTY, true, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, !DIRTY, true, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, !DIRTY, true, MARKER_DATABASE);
public void testCleanRefreshWithoutDataCacheDoesNotHitDatabase() {
verifyRefresh(!WITH_DATACACHE, NOLOCK, !DIRTY, REFRESH_FROM_DATACACHE, MARKER_CACHE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, !DIRTY, REFRESH_FROM_DATACACHE, MARKER_CACHE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, !DIRTY, REFRESH_FROM_DATACACHE, MARKER_CACHE);
verifyRefresh(!WITH_DATACACHE, NOLOCK, !DIRTY, false, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, !DIRTY, false, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, !DIRTY, false, MARKER_DATABASE);
verifyRefresh(!WITH_DATACACHE, NOLOCK, !DIRTY, !REFRESH_FROM_DATACACHE, MARKER_CACHE);
verifyRefresh(!WITH_DATACACHE, LockModeType.READ, !DIRTY, !REFRESH_FROM_DATACACHE, MARKER_CACHE);
verifyRefresh(!WITH_DATACACHE, LockModeType.WRITE, !DIRTY, !REFRESH_FROM_DATACACHE, MARKER_CACHE);
}
/**
@ -430,7 +431,7 @@ public class TestDataCacheBehavesIdentical extends AbstractTestCase {
* @param lock
*/
public void verifyDeleteDetectionOnRefresh(boolean useDataCache,
LockModeType lock) {
boolean dirty, LockModeType lock, Class expectedExceptionType) {
OpenJPAEntityManagerFactorySPI emf = (useDataCache)
? emfWithDataCache : emfWithoutDataCache;
@ -465,34 +466,59 @@ public class TestDataCacheBehavesIdentical extends AbstractTestCase {
*
*/
em.getTransaction().begin();
if (lock != null)
em.getFetchPlan().setReadLockMode(lock);
em.getFetchPlan().setReadLockMode(lock);
if (dirty)
pc.setName("Dirty Name");
try {
em.refresh(pc);
fail("expected EntityNotFoundException for PObject:" + oid);
} catch (EntityNotFoundException ex) {
// we are good
if (expectedExceptionType != null) {
fail("expected " + expectedExceptionType.getSimpleName() +
" for PObject:" + oid);
}
} catch (Exception ex) {
ex.printStackTrace();
fail("expected EntityNotFoundException for PObject:" + oid);
boolean expectedException = expectedExceptionType != null &&
expectedExceptionType.isAssignableFrom(ex.getClass());
if (!expectedException) {
ex.printStackTrace();
String error = (expectedExceptionType == null)
? "no exception" : expectedExceptionType.getName();
fail("expected " + error + " for PObject:" + oid);
}
} finally {
em.getTransaction().rollback();
}
}
public void testDeleteIsDetectedOnRefreshWithLockWithActiveDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, LockModeType.READ);
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, LockModeType.WRITE);
public void testDeleteIsNotDetectedOnCleanRefreshWithoutLockWithDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, NOLOCK, NO_ERROR);
}
public void testDeleteIsNotDetectedOnRefreshWithNoLockWithActiveDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, NOLOCK);
public void testDeleteIsDetectedOnCleanRefreshWithLockWithDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, !DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsNotDetectedOnDirtyRefreshWithoutLockWithDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, NOLOCK, NO_ERROR);
}
public void testDeleteIsDetectedOnRefreshAlwaysWithoutDataCache() {
verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, NOLOCK);
verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, LockModeType.READ);
verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, LockModeType.WRITE);
public void testDeleteIsDetectedOnDirtyRefreshWithLockWithDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsDetectedOnDirtyRefreshWitDataCache() {
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
verifyDeleteDetectionOnRefresh(WITH_DATACACHE, DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsDetectedOnCleanRefreshWithoutLockWithoutDataCache() {
verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, NOLOCK, ENTITY_NOT_FOUND_ERROR);
}
public void testDeleteIsDetectedOnCleanRefreshWithLockWithoutDataCache() {
verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, LockModeType.READ, ENTITY_NOT_FOUND_ERROR);
verifyDeleteDetectionOnRefresh(!WITH_DATACACHE, !DIRTY, LockModeType.WRITE, ENTITY_NOT_FOUND_ERROR);
}
}