mirror of https://github.com/apache/openjpa.git
PNewProvisional
git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@450321 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9443b9f9bc
commit
c6537ccba6
|
@ -627,6 +627,10 @@ public class EmbedFieldStrategy
|
|||
return isFlushed();
|
||||
}
|
||||
|
||||
public boolean isProvisional() {
|
||||
return _owner.isProvisional();
|
||||
}
|
||||
|
||||
public BitSet getLoaded() {
|
||||
// consider everything loaded
|
||||
if (_full == null) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,10 @@ public class DetachedValueStateManager
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isProvisional() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BitSet getLoaded() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -317,6 +317,10 @@ public class ObjectIdStateManager
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isProvisional() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BitSet getLoaded() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue