PNewProvisional

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@450321 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Kim 2006-09-27 05:24:44 +00:00
parent 9443b9f9bc
commit c6537ccba6
14 changed files with 187 additions and 38 deletions

View File

@ -627,6 +627,10 @@ public class EmbedFieldStrategy
return isFlushed();
}
public boolean isProvisional() {
return _owner.isProvisional();
}
public BitSet getLoaded() {
// consider everything loaded
if (_full == null) {

View File

@ -94,7 +94,7 @@ class AttachManager {
CallbackException excep = null;
try {
return attach(pc, null, null, null);
return attach(pc, null, null, null, true);
} catch (CallbackException ce) {
excep = ce;
return null; // won't be reached as the exceps will be rethrown
@ -122,7 +122,7 @@ class AttachManager {
int i = 0;
for (Iterator itr = instances.iterator(); itr.hasNext(); i++) {
try {
attached[i] = attach(itr.next(), null, null, null);
attached[i] = attach(itr.next(), null, null, null, true);
} catch (OpenJPAException ke) {
// track exceptions and optimistic failed objects
if (opt && !(ke instanceof OptimisticException))
@ -212,9 +212,10 @@ class AttachManager {
* @param into the instance we're attaching into
* @param owner state manager for <code>into</code>
* @param ownerMeta the field we traversed to find <code>toAttach</code>
* @param explicit whether to make new instances explicitly persistent
*/
Object attach(Object toAttach, PersistenceCapable into,
OpenJPAStateManager owner, ValueMetaData ownerMeta) {
OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit) {
if (toAttach == null)
return null;
@ -233,7 +234,7 @@ class AttachManager {
getMetaDataRepositoryInstance().getMetaData(toAttach.getClass(),
_broker.getClassLoader(), true);
return getStrategy(toAttach).attach(this, toAttach, meta, into,
owner, ownerMeta);
owner, ownerMeta, explicit);
}
/**

View File

@ -55,10 +55,11 @@ abstract class AttachStrategy
* @param into instance we're attaching into
* @param owner state manager for <code>into</code>
* @param ownerMeta field we traversed to find <code>toAttach</code>
* @param explicit whether to make new instances explicitly persistent
*/
public abstract Object attach(AttachManager manager,
Object toAttach, ClassMetaData meta, PersistenceCapable into,
OpenJPAStateManager owner, ValueMetaData ownerMeta);
OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit);
/**
* Return the identity of the given detached instance.
@ -73,10 +74,12 @@ abstract class AttachStrategy
int field);
/**
* Return a PNew managed object for the given detached instance.
* Return a PNew/PNewProvisional managed object for the given detached
* instance.
*/
protected StateManagerImpl persist(AttachManager manager,
PersistenceCapable pc, ClassMetaData meta, Object appId) {
PersistenceCapable pc, ClassMetaData meta, Object appId,
boolean explicit) {
PersistenceCapable newInstance;
if (!manager.getCopyNew())
newInstance = pc;
@ -86,7 +89,7 @@ abstract class AttachStrategy
newInstance = pc.pcNewInstance(null, appId, false);
return (StateManagerImpl) manager.getBroker().persist
(newInstance, appId, manager.getBehavior());
(newInstance, appId, explicit, manager.getBehavior());
}
/**
@ -191,7 +194,7 @@ abstract class AttachStrategy
manager.getDetachedObjectId(frmpc))) {
intopc = null;
}
frmpc = manager.attach(frmpc, intopc, sm, fmd);
frmpc = manager.attach(frmpc, intopc, sm, fmd, false);
}
if (frmpc != topc)
sm.settingObjectField(into, i, topc, frmpc, set);
@ -320,7 +323,7 @@ abstract class AttachStrategy
if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
elem = getReference(manager, itr.next(), sm, vmd);
else
elem = manager.attach(itr.next(), null, sm, vmd);
elem = manager.attach(itr.next(), null, sm, vmd, false);
coll.add(elem);
}
return coll;
@ -432,13 +435,13 @@ abstract class AttachStrategy
if (keymd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
key = getReference(manager, key, sm, keymd);
else
key = manager.attach(key, null, sm, keymd);
key = manager.attach(key, null, sm, keymd, false);
val = entry.getValue();
if (valmd.isDeclaredTypePC()) {
if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
val = getReference(manager, val, sm, valmd);
else
val = manager.attach(val, null, sm, valmd);
val = manager.attach(val, null, sm, valmd, false);
}
map.put(key, val);
}
@ -449,7 +452,8 @@ abstract class AttachStrategy
if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
val = getReference(manager, entry.getValue(), sm, valmd);
else
val = manager.attach(entry.getValue(), null, sm, valmd);
val = manager.attach(entry.getValue(), null, sm, valmd,
false);
entry.setValue(val);
}
}
@ -479,7 +483,7 @@ abstract class AttachStrategy
if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
elem = getReference(manager, elem, sm, vmd);
else
elem = manager.attach(elem, null, sm, vmd);
elem = manager.attach(elem, null, sm, vmd, false);
}
diff = diff || !equals(elem, Array.get(toa, i), pc);
Array.set(newa, i, elem);

View File

@ -2152,7 +2152,25 @@ public class BrokerImpl
// Object lifecycle
////////////////////
public void persist(Object obj, OpCallbacks call) {
persist(obj, null, true, call);
}
public OpenJPAStateManager persist(Object obj, Object id,
OpCallbacks call) {
return persist(obj, id, true, call);
}
public void persistAll(Collection objs, OpCallbacks call) {
persistAll(objs, true, call);
}
/**
* Persist the given objects. Indicate whether this was an explicit persist
* (PNEW) or a provisonal persist (PNEWPROVISIONAL).
*/
public void persistAll(Collection objs, boolean explicit,
OpCallbacks call) {
if (objs.isEmpty())
return;
@ -2163,7 +2181,7 @@ public class BrokerImpl
for (Iterator itr = objs.iterator(); itr.hasNext();) {
try {
persist(itr.next(), call);
persist(itr.next(), explicit, call);
} catch (UserException ue) {
exceps = add(exceps, ue);
}
@ -2212,11 +2230,20 @@ public class BrokerImpl
throw err.setNestedThrowables(t).setFatal(fatal);
}
public void persist(Object obj, OpCallbacks call) {
persist(obj, null, call);
/**
* Persist the given object. Indicate whether this was an explicit persist
* (PNEW) or a provisonal persist (PNEWPROVISIONAL)
*/
public void persist(Object obj, boolean explicit, OpCallbacks call) {
persist(obj, null, explicit, call);
}
public OpenJPAStateManager persist(Object obj, Object id,
/**
* Persist the given object. Indicate whether this was an explicit persist
* (PNEW) or a provisonal persist (PNEWPROVISIONAL).
* See {@link Broker} for details on this method.
*/
public OpenJPAStateManager persist(Object obj, Object id, boolean explicit,
OpCallbacks call) {
if (obj == null)
return null;
@ -2299,9 +2326,12 @@ public class BrokerImpl
// create new sm
sm = new StateManagerImpl(id, meta, this);
if ((_flags & FLAG_ACTIVE) != 0)
sm.initialize(pc, PCState.PNEW);
else
if ((_flags & FLAG_ACTIVE) != 0) {
if (explicit)
sm.initialize(pc, PCState.PNEW);
else
sm.initialize(pc, PCState.PNEWPROVISIONAL);
} else
sm.initialize(pc, PCState.PNONTRANSNEW);
if ((action & OpCallbacks.ACT_CASCADE) != 0)
sm.cascadePersist(call);

View File

@ -70,7 +70,7 @@ class DetachedStateAttachStrategy
public Object attach(AttachManager manager, Object toAttach,
ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner,
ValueMetaData ownerMeta) {
ValueMetaData ownerMeta, boolean explicit) {
BrokerImpl broker = manager.getBroker();
PersistenceCapable pc = (PersistenceCapable) toAttach;
@ -94,7 +94,8 @@ class DetachedStateAttachStrategy
sm = (StateManagerImpl) broker.embed(into, null, owner, ownerMeta);
into = sm.getPersistenceCapable();
} else if (state == null) {
sm = persist(manager, pc, meta, ApplicationIds.create(pc, meta));
sm = persist(manager, pc, meta, ApplicationIds.create(pc, meta),
explicit);
into = sm.getPersistenceCapable();
} else if (!embedded && into == null) {
Object id = getDetachedObjectId(manager, pc);
@ -117,7 +118,7 @@ class DetachedStateAttachStrategy
// the transaction was rolled back; the danger is that
// the instance was made persistent, detached, committed,
// and then deleted, but this is an uncommon case
sm = persist(manager, pc, meta, id);
sm = persist(manager, pc, meta, id, explicit);
into = sm.getPersistenceCapable();
// nullify the state, since the new instance won't have one
@ -144,7 +145,7 @@ class DetachedStateAttachStrategy
// only attach fields in the FG of the detached instance; new
// instances get all their fields attached
if (fields == null || fields.get(i))
attachField(manager, pc, sm, fmds[i], true);
attachField(manager, pc, sm, fmds[i], false);
}
}
finally {

View File

@ -87,7 +87,7 @@ public class DetachedStateManager
public Object attach(AttachManager manager, Object toAttach,
ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner,
ValueMetaData ownerMeta) {
ValueMetaData ownerMeta, boolean explicit) {
BrokerImpl broker = manager.getBroker();
StateManagerImpl sm = null;
if (_embedded) {
@ -225,7 +225,8 @@ public class DetachedStateManager
PersistenceCapable toPC = null;
if (objval != null && fields[i].isEmbeddedPC())
toPC = (PersistenceCapable) objval;
objval = manager.attach(objval, toPC, sm, fields[i]);
objval = manager.attach(objval, toPC, sm, fields[i],
false);
}
if (_dirty.get(i))
sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
@ -688,6 +689,10 @@ public class DetachedStateManager
throw new UnsupportedOperationException();
}
public boolean isProvisional() {
throw new UnsupportedOperationException();
}
public BitSet getLoaded() {
return _loaded;
}

View File

@ -101,6 +101,10 @@ public class DetachedValueStateManager
return false;
}
public boolean isProvisional() {
return false;
}
public BitSet getLoaded() {
throw new UnsupportedOperationException();
}

View File

@ -317,6 +317,10 @@ public class ObjectIdStateManager
return false;
}
public boolean isProvisional() {
return false;
}
public BitSet getLoaded() {
throw new UnsupportedOperationException();
}

View File

@ -120,6 +120,11 @@ public interface OpenJPAStateManager
*/
public boolean isFlushedDirty();
/**
* Return whether this object is provisionally persistent.
*/
public boolean isProvisional();
/**
* Return a read-only mask of the indexes of all loaded fields.
*/

View File

@ -62,6 +62,11 @@ public class PCState
*/
public static final PCState PNEWDELETED = new PNewDeletedState();
/**
* Persistent-New-Provisional
*/
public static final PCState PNEWPROVISIONAL = new PNewProvisionalState();
/**
* Persistent-Nontransactinoal
*/
@ -228,6 +233,14 @@ public class PCState
return this;
}
/**
* Return the state to transition to after making no longer provisional.
* The context is not given because no actions should be taken.
*/
PCState nonprovisional() {
return this;
}
/**
* Perform any actions necesssary and return the proper lifecycle state
* on a call to {@link StoreContext#nontransactional} with the given
@ -402,6 +415,15 @@ public class PCState
return false;
}
/**
* Return whether this is a state that will become transient
* at the end of the next transaction.
* Returns <code>false</code> by default.
*/
boolean isProvisional() {
return false;
}
/**
* Whether this state requires a version check when being flushed,
* assuming the system is configured for version checks.
@ -430,6 +452,8 @@ public class PCState
return PDELETED;
if (this instanceof PNewDeletedState)
return PNEWDELETED;
if (this instanceof PNewProvisionalState)
return PNEWPROVISIONAL;
if (this instanceof PNonTransState)
return PNONTRANS;
if (this instanceof PNonTransDirtyState)

View File

@ -0,0 +1,48 @@
/*
* Copyright 2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openjpa.kernel;
/**
* Lifecycle state.
* Represents an instance that was made persistent via reachability within the
* current transaction.
*
* @author Steve Kim
* @author: Abe White
*/
class PNewProvisionalState
extends PNewState {
PCState persist(StateManagerImpl context) {
return PNEW;
}
PCState nonprovisional() {
return PNEW;
}
PCState commit(StateManagerImpl context) {
return TRANSIENT;
}
PCState commitRetain(StateManagerImpl context) {
return TRANSIENT;
}
boolean isProvisional() {
return true;
}
}

View File

@ -250,21 +250,22 @@ class SingleFieldManager
case JavaTypes.PC_UNTYPED:
if (!_broker.isDetachedNew() && _broker.isDetached(objval))
return; // allow but ignore
_broker.persist(objval, call);
_broker.persist(objval, false, call);
break;
case JavaTypes.ARRAY:
_broker.persistAll(Arrays.asList((Object[]) objval), call);
_broker.persistAll(Arrays.asList((Object[]) objval), false,
call);
break;
case JavaTypes.COLLECTION:
_broker.persistAll((Collection) objval, call);
_broker.persistAll((Collection) objval, false, call);
break;
case JavaTypes.MAP:
if (fmd.getKey().getCascadePersist()
== ValueMetaData.CASCADE_IMMEDIATE)
_broker.persistAll(((Map) objval).keySet(), call);
_broker.persistAll(((Map) objval).keySet(), false, call);
if (fmd.getElement().getCascadePersist()
== ValueMetaData.CASCADE_IMMEDIATE)
_broker.persistAll(((Map) objval).values(), call);
_broker.persistAll(((Map) objval).values(), false, call);
break;
}
}
@ -467,7 +468,9 @@ class SingleFieldManager
return false;
// perform pers-by-reach and dependent refs
boolean ret = preFlush(fmd, call);
boolean ret = false;
if (!_sm.isProvisional())
ret = preFlush(fmd, call);
// manage inverses
InverseManager manager = _broker.getInverseManager();
@ -740,7 +743,7 @@ class SingleFieldManager
Exceptions.toString(_sm.getManagedInstance()))).
setFailedObject(obj);
} else
sm = _broker.persist(obj, null, call);
sm = _broker.persist(obj, null, true, call);
if (sm != null) {
// if deleted and not managed inverse, die
@ -750,6 +753,7 @@ class SingleFieldManager
Exceptions.toString(obj), vmd,
Exceptions.toString(_sm.getManagedInstance()))).
setFailedObject(obj);
((StateManagerImpl) sm).nonprovisional();
((StateManagerImpl) sm).setDereferencedDependent(false, true);
}
}

View File

@ -993,6 +993,16 @@ public class StateManagerImpl
setPCState(_state.transactional(this));
}
/**
* Delegates to the current state.
*
* @see PCState#nonprovisional
* @see Broker#nonprovisional
*/
void nonprovisional() {
setPCState(_state.nonprovisional());
}
/**
* Delegates to the current state.
*
@ -1252,6 +1262,10 @@ public class StateManagerImpl
return _state.isPendingTransactional();
}
public boolean isProvisional() {
return _state.isProvisional();
}
public boolean isPersistent() {
return _state.isPersistent();
}

View File

@ -59,7 +59,7 @@ class VersionAttachStrategy
public Object attach(AttachManager manager, Object toAttach,
ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner,
ValueMetaData ownerMeta) {
ValueMetaData ownerMeta, boolean explicit) {
BrokerImpl broker = manager.getBroker();
PersistenceCapable pc = (PersistenceCapable) toAttach;
@ -82,7 +82,8 @@ class VersionAttachStrategy
sm = (StateManagerImpl) broker.embed(into, null, owner, ownerMeta);
into = sm.getPersistenceCapable();
} else if (isNew) {
sm = persist(manager, pc, meta, ApplicationIds.create(pc, meta));
sm = persist(manager, pc, meta, ApplicationIds.create(pc, meta),
explicit);
into = sm.getPersistenceCapable();
} else if (!embedded && into == null) {
Object id = getDetachedObjectId(manager, toAttach);
@ -235,8 +236,8 @@ class VersionAttachStrategy
PersistenceCapable intoPC = (into == null) ? null
: into.getPersistenceCapable();
if (vmd.isEmbedded())
return manager.attach(pc, intoPC, sm, vmd);
return manager.attach(pc, intoPC, null, null);
return manager.attach(pc, intoPC, sm, vmd, false);
return manager.attach(pc, intoPC, null, null, false);
}
/**