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(); return isFlushed();
} }
public boolean isProvisional() {
return _owner.isProvisional();
}
public BitSet getLoaded() { public BitSet getLoaded() {
// consider everything loaded // consider everything loaded
if (_full == null) { if (_full == null) {

View File

@ -94,7 +94,7 @@ class AttachManager {
CallbackException excep = null; CallbackException excep = null;
try { try {
return attach(pc, null, null, null); return attach(pc, null, null, null, true);
} catch (CallbackException ce) { } catch (CallbackException ce) {
excep = ce; excep = ce;
return null; // won't be reached as the exceps will be rethrown return null; // won't be reached as the exceps will be rethrown
@ -122,7 +122,7 @@ class AttachManager {
int i = 0; int i = 0;
for (Iterator itr = instances.iterator(); itr.hasNext(); i++) { for (Iterator itr = instances.iterator(); itr.hasNext(); i++) {
try { try {
attached[i] = attach(itr.next(), null, null, null); attached[i] = attach(itr.next(), null, null, null, true);
} catch (OpenJPAException ke) { } catch (OpenJPAException ke) {
// track exceptions and optimistic failed objects // track exceptions and optimistic failed objects
if (opt && !(ke instanceof OptimisticException)) if (opt && !(ke instanceof OptimisticException))
@ -212,9 +212,10 @@ class AttachManager {
* @param into the instance we're attaching into * @param into the instance we're attaching into
* @param owner state manager for <code>into</code> * @param owner state manager for <code>into</code>
* @param ownerMeta the field we traversed to find <code>toAttach</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, Object attach(Object toAttach, PersistenceCapable into,
OpenJPAStateManager owner, ValueMetaData ownerMeta) { OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit) {
if (toAttach == null) if (toAttach == null)
return null; return null;
@ -233,7 +234,7 @@ class AttachManager {
getMetaDataRepositoryInstance().getMetaData(toAttach.getClass(), getMetaDataRepositoryInstance().getMetaData(toAttach.getClass(),
_broker.getClassLoader(), true); _broker.getClassLoader(), true);
return getStrategy(toAttach).attach(this, toAttach, meta, into, 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 into instance we're attaching into
* @param owner state manager for <code>into</code> * @param owner state manager for <code>into</code>
* @param ownerMeta field we traversed to find <code>toAttach</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, public abstract Object attach(AttachManager manager,
Object toAttach, ClassMetaData meta, PersistenceCapable into, Object toAttach, ClassMetaData meta, PersistenceCapable into,
OpenJPAStateManager owner, ValueMetaData ownerMeta); OpenJPAStateManager owner, ValueMetaData ownerMeta, boolean explicit);
/** /**
* Return the identity of the given detached instance. * Return the identity of the given detached instance.
@ -73,10 +74,12 @@ abstract class AttachStrategy
int field); 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, protected StateManagerImpl persist(AttachManager manager,
PersistenceCapable pc, ClassMetaData meta, Object appId) { PersistenceCapable pc, ClassMetaData meta, Object appId,
boolean explicit) {
PersistenceCapable newInstance; PersistenceCapable newInstance;
if (!manager.getCopyNew()) if (!manager.getCopyNew())
newInstance = pc; newInstance = pc;
@ -86,7 +89,7 @@ abstract class AttachStrategy
newInstance = pc.pcNewInstance(null, appId, false); newInstance = pc.pcNewInstance(null, appId, false);
return (StateManagerImpl) manager.getBroker().persist return (StateManagerImpl) manager.getBroker().persist
(newInstance, appId, manager.getBehavior()); (newInstance, appId, explicit, manager.getBehavior());
} }
/** /**
@ -191,7 +194,7 @@ abstract class AttachStrategy
manager.getDetachedObjectId(frmpc))) { manager.getDetachedObjectId(frmpc))) {
intopc = null; intopc = null;
} }
frmpc = manager.attach(frmpc, intopc, sm, fmd); frmpc = manager.attach(frmpc, intopc, sm, fmd, false);
} }
if (frmpc != topc) if (frmpc != topc)
sm.settingObjectField(into, i, topc, frmpc, set); sm.settingObjectField(into, i, topc, frmpc, set);
@ -320,7 +323,7 @@ abstract class AttachStrategy
if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
elem = getReference(manager, itr.next(), sm, vmd); elem = getReference(manager, itr.next(), sm, vmd);
else else
elem = manager.attach(itr.next(), null, sm, vmd); elem = manager.attach(itr.next(), null, sm, vmd, false);
coll.add(elem); coll.add(elem);
} }
return coll; return coll;
@ -432,13 +435,13 @@ abstract class AttachStrategy
if (keymd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) if (keymd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
key = getReference(manager, key, sm, keymd); key = getReference(manager, key, sm, keymd);
else else
key = manager.attach(key, null, sm, keymd); key = manager.attach(key, null, sm, keymd, false);
val = entry.getValue(); val = entry.getValue();
if (valmd.isDeclaredTypePC()) { if (valmd.isDeclaredTypePC()) {
if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
val = getReference(manager, val, sm, valmd); val = getReference(manager, val, sm, valmd);
else else
val = manager.attach(val, null, sm, valmd); val = manager.attach(val, null, sm, valmd, false);
} }
map.put(key, val); map.put(key, val);
} }
@ -449,7 +452,8 @@ abstract class AttachStrategy
if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) if (valmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
val = getReference(manager, entry.getValue(), sm, valmd); val = getReference(manager, entry.getValue(), sm, valmd);
else else
val = manager.attach(entry.getValue(), null, sm, valmd); val = manager.attach(entry.getValue(), null, sm, valmd,
false);
entry.setValue(val); entry.setValue(val);
} }
} }
@ -479,7 +483,7 @@ abstract class AttachStrategy
if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE) if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_NONE)
elem = getReference(manager, elem, sm, vmd); elem = getReference(manager, elem, sm, vmd);
else 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); diff = diff || !equals(elem, Array.get(toa, i), pc);
Array.set(newa, i, elem); Array.set(newa, i, elem);

View File

@ -2152,7 +2152,25 @@ public class BrokerImpl
// Object lifecycle // 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) { 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()) if (objs.isEmpty())
return; return;
@ -2163,7 +2181,7 @@ public class BrokerImpl
for (Iterator itr = objs.iterator(); itr.hasNext();) { for (Iterator itr = objs.iterator(); itr.hasNext();) {
try { try {
persist(itr.next(), call); persist(itr.next(), explicit, call);
} catch (UserException ue) { } catch (UserException ue) {
exceps = add(exceps, ue); exceps = add(exceps, ue);
} }
@ -2212,11 +2230,20 @@ public class BrokerImpl
throw err.setNestedThrowables(t).setFatal(fatal); 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) { OpCallbacks call) {
if (obj == null) if (obj == null)
return null; return null;
@ -2299,9 +2326,12 @@ public class BrokerImpl
// create new sm // create new sm
sm = new StateManagerImpl(id, meta, this); sm = new StateManagerImpl(id, meta, this);
if ((_flags & FLAG_ACTIVE) != 0) if ((_flags & FLAG_ACTIVE) != 0) {
sm.initialize(pc, PCState.PNEW); if (explicit)
else sm.initialize(pc, PCState.PNEW);
else
sm.initialize(pc, PCState.PNEWPROVISIONAL);
} else
sm.initialize(pc, PCState.PNONTRANSNEW); sm.initialize(pc, PCState.PNONTRANSNEW);
if ((action & OpCallbacks.ACT_CASCADE) != 0) if ((action & OpCallbacks.ACT_CASCADE) != 0)
sm.cascadePersist(call); sm.cascadePersist(call);

View File

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

View File

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

View File

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

View File

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

View File

@ -120,6 +120,11 @@ public interface OpenJPAStateManager
*/ */
public boolean isFlushedDirty(); 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. * 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(); public static final PCState PNEWDELETED = new PNewDeletedState();
/**
* Persistent-New-Provisional
*/
public static final PCState PNEWPROVISIONAL = new PNewProvisionalState();
/** /**
* Persistent-Nontransactinoal * Persistent-Nontransactinoal
*/ */
@ -228,6 +233,14 @@ public class PCState
return this; 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 * Perform any actions necesssary and return the proper lifecycle state
* on a call to {@link StoreContext#nontransactional} with the given * on a call to {@link StoreContext#nontransactional} with the given
@ -402,6 +415,15 @@ public class PCState
return false; 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, * Whether this state requires a version check when being flushed,
* assuming the system is configured for version checks. * assuming the system is configured for version checks.
@ -430,6 +452,8 @@ public class PCState
return PDELETED; return PDELETED;
if (this instanceof PNewDeletedState) if (this instanceof PNewDeletedState)
return PNEWDELETED; return PNEWDELETED;
if (this instanceof PNewProvisionalState)
return PNEWPROVISIONAL;
if (this instanceof PNonTransState) if (this instanceof PNonTransState)
return PNONTRANS; return PNONTRANS;
if (this instanceof PNonTransDirtyState) 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: case JavaTypes.PC_UNTYPED:
if (!_broker.isDetachedNew() && _broker.isDetached(objval)) if (!_broker.isDetachedNew() && _broker.isDetached(objval))
return; // allow but ignore return; // allow but ignore
_broker.persist(objval, call); _broker.persist(objval, false, call);
break; break;
case JavaTypes.ARRAY: case JavaTypes.ARRAY:
_broker.persistAll(Arrays.asList((Object[]) objval), call); _broker.persistAll(Arrays.asList((Object[]) objval), false,
call);
break; break;
case JavaTypes.COLLECTION: case JavaTypes.COLLECTION:
_broker.persistAll((Collection) objval, call); _broker.persistAll((Collection) objval, false, call);
break; break;
case JavaTypes.MAP: case JavaTypes.MAP:
if (fmd.getKey().getCascadePersist() if (fmd.getKey().getCascadePersist()
== ValueMetaData.CASCADE_IMMEDIATE) == ValueMetaData.CASCADE_IMMEDIATE)
_broker.persistAll(((Map) objval).keySet(), call); _broker.persistAll(((Map) objval).keySet(), false, call);
if (fmd.getElement().getCascadePersist() if (fmd.getElement().getCascadePersist()
== ValueMetaData.CASCADE_IMMEDIATE) == ValueMetaData.CASCADE_IMMEDIATE)
_broker.persistAll(((Map) objval).values(), call); _broker.persistAll(((Map) objval).values(), false, call);
break; break;
} }
} }
@ -467,7 +468,9 @@ class SingleFieldManager
return false; return false;
// perform pers-by-reach and dependent refs // perform pers-by-reach and dependent refs
boolean ret = preFlush(fmd, call); boolean ret = false;
if (!_sm.isProvisional())
ret = preFlush(fmd, call);
// manage inverses // manage inverses
InverseManager manager = _broker.getInverseManager(); InverseManager manager = _broker.getInverseManager();
@ -740,7 +743,7 @@ class SingleFieldManager
Exceptions.toString(_sm.getManagedInstance()))). Exceptions.toString(_sm.getManagedInstance()))).
setFailedObject(obj); setFailedObject(obj);
} else } else
sm = _broker.persist(obj, null, call); sm = _broker.persist(obj, null, true, call);
if (sm != null) { if (sm != null) {
// if deleted and not managed inverse, die // if deleted and not managed inverse, die
@ -750,6 +753,7 @@ class SingleFieldManager
Exceptions.toString(obj), vmd, Exceptions.toString(obj), vmd,
Exceptions.toString(_sm.getManagedInstance()))). Exceptions.toString(_sm.getManagedInstance()))).
setFailedObject(obj); setFailedObject(obj);
((StateManagerImpl) sm).nonprovisional();
((StateManagerImpl) sm).setDereferencedDependent(false, true); ((StateManagerImpl) sm).setDereferencedDependent(false, true);
} }
} }

View File

@ -993,6 +993,16 @@ public class StateManagerImpl
setPCState(_state.transactional(this)); 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. * Delegates to the current state.
* *
@ -1252,6 +1262,10 @@ public class StateManagerImpl
return _state.isPendingTransactional(); return _state.isPendingTransactional();
} }
public boolean isProvisional() {
return _state.isProvisional();
}
public boolean isPersistent() { public boolean isPersistent() {
return _state.isPersistent(); return _state.isPersistent();
} }

View File

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