mirror of https://github.com/apache/openjpa.git
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:
parent
514a4bb907
commit
71519b0808
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue