SQLStateManagerpublic class SQLStateManager extends Object implements StateManager, TestStateManager, Cloneable
Fields Summary |
---|
private static final int | PRESENCE_MASK | private static final int | SET_MASK | private static final int | MAX_MASKS | private BitSet | fieldMasks | public ArrayList | hiddenValuesArray of Object. | private ClassDesc | persistenceConfig | private PersistenceManager | persistenceManager | private PersistenceStore | store | private SQLStateManager | beforeImage | private Object | persistentObject | private Object | objectId | private com.sun.jdo.spi.persistence.support.sqlstore.state.LifeCycleState | state | private static final short | ST_UPDATE_DISABLEDThis flag is used to disable updates due to dependency management. | private static final short | ST_REGISTERED | private static final short | ST_VISITED | private static final short | ST_PREPARED_PHASE_II | private static final short | ST_FIELD_TRACKING_INPROGRESS | private static final short | ST_DELETE_INPROGRESS | private static final short | ST_VALIDATION_FAILED | private short | stateFlags | private boolean | isReplacementInstance | private boolean | needsRegisterAtRollback | private boolean | needsVerifyAtDeregister | private boolean | valid | private com.sun.jdo.spi.persistence.support.sqlstore.sql.UpdateObjectDescImpl | updateDescStores the updates to the associated object. | private HashSet | updatedForeignReferencesContains state managers depending on this object. | private int | referenceCountCounts the foreign state managers this state manager depends on. | private final com.sun.jdo.spi.persistence.utility.Semaphore | lockSerializes access to this StateManager. | private static com.sun.jdo.spi.persistence.utility.logging.Logger | loggerThe logger. | private static final ResourceBundle | messagesI18N message handler. | public static final String | USE_BATCH_PROPERTYName of the USE_BATCH property. | private static final boolean | USE_BATCHProperty to swich on/off batching. Note, the default is true, meaning we
try to do batching if the property is not specified. |
Constructors Summary |
---|
public SQLStateManager(PersistenceStore store, ClassDesc persistenceConfig)Construct a new SQLStateManager so that it locks or does not lock as
per whether or not it is used in a managed environment. // NOI18N
this.store = store;
this.persistenceConfig = persistenceConfig;
if (EJBHelper.isManaged()) {
this.lock = new NullSemaphore("SQLStateManager"); // NOI18N
} else {
this.lock = new SemaphoreImpl("SQLStateManager"); // NOI18N
}
|
Methods Summary |
---|
private void | addCollectionRelationship(ForeignFieldDesc fieldDesc, java.util.ArrayList addedList, ForeignFieldDesc inverseFieldDesc, java.util.ArrayList newlyRegisteredSMs, boolean updateInverseRelationshipField, boolean managedRelationshipInProgress)Sets the relationship for the objects added to a collection relationship.
JDOUserException ex = null;
for (int i = 0; i < addedList.size(); i++) {
Object addedObject = addedList.get(i);
SQLStateManager addedSM = getAddedSM(addedObject, newlyRegisteredSMs);
// addedSM == null can happen if the collection is non-SCO and contains
// transient instances which don't become persistent until commit.
if (addedSM != null) {
if (addedSM.isDeleted()) {
// For managed relationships, if the addedObject is deleted, we need
// to throw an exception at the end and the exception should include
// the deleted objects in its failedObjectArray.
if (inverseFieldDesc != null) {
if (ex == null) {
ex = new JDOUserException(I18NHelper.getMessage(messages,
"jdo.lifecycle.deleted.accessField")); // NOI18N
}
ex.addFailedObject(addedObject);
}
continue;
}
// The collection side never has the foreign key, i.e.
// it's never processed during relationship management,
// because data store updates are already done at that time.
if (!managedRelationshipInProgress) {
updateRelationshipInDataStore(fieldDesc, addedSM, null, inverseFieldDesc, false);
// Relationship management
if (updateInverseRelationshipField && inverseFieldDesc != null) {
addedSM.addRelationship(inverseFieldDesc, this);
}
}
}
}
if (ex != null) {
throw ex;
}
| public void | addDependency(StateManager sm)This method adds the dependency between this StateManager
and the other.
if (logger.isLoggable()) {
Object[] items = new Object[] {this, sm};
logger.fine("sqlstore.sqlstatemanager.adddependency", items); // NOI18N
}
// The simple solution is to call addUpdatedForeignReference()
// internally. It might try to reregister both instances again,
// but the caller should clean up the cache. e.g. the
// PersistenceManager MUST replace the deleted StateManager
// with the new instance in the weak cache AFTER this call.
SQLStateManager other = (SQLStateManager)sm;
if (!state.isNew() || !state.isDeleted()) {
// Do not need to add a dependency to a new-deleted instance as
// its flush is a no-op any way.
// First parameter == null marks a non removable dependency.
this.addUpdatedForeignReference(null, other);
} else if ((other.stateFlags & ST_REGISTERED) == 0) {
// If we did not add a dependency, we still need to register the other
// instance if it is not yet registered.
persistenceManager.registerInstance(other, other.getObjectId(), false, true);
other.stateFlags |= ST_REGISTERED;
}
| private void | addJoinTableEntry(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, ForeignFieldDesc inverseFieldDesc)Schedules the creation of a jointable entry between this and the added
state manager. A scheduled removal of the jointable entry between these
two is simply removed. The creation is scheduled on the local side.
For dependency management, the side creating the jointable entry has
to wait for the other to become persistent. The same dependency applies
to foreign key relationships, see {@link #setForeignKey}.
RESOLVE: What happens, if a field descriptor is null, e.g. for one
way relationships, as the descriptors are taken as keys during scheduling?
// Cleanup dependencies.
// Note: The following lines break deadlock detection for circular dependencies.
//this.removeUpdatedForeignReference(addedSM);
//addedSM.removeUpdatedForeignReference(this);
// Remove scheduled removal on this side.
if (fieldDesc != null && getUpdateDesc().removeUpdatedJoinTableRelationship(
fieldDesc, addedSM, ActionDesc.LOG_DESTROY) == false) {
// Remove scheduled removal on the other side.
if (inverseFieldDesc == null || addedSM.getUpdateDesc().removeUpdatedJoinTableRelationship(
inverseFieldDesc, this, ActionDesc.LOG_DESTROY) == false) {
// Schedule creation on this side.
// The field descriptor taken as key must not be null, see above!
getUpdateDesc().recordUpdatedJoinTableRelationship(
fieldDesc, this, addedSM, ActionDesc.LOG_CREATE);
// The side creating the jointable entry has to wait for the other to become persistent.
registerCreateDependency(inverseFieldDesc, addedSM);
}
} else if (fieldDesc == null) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.cantschedulejointable", // NOI18N
this.getPersistenceConfig().getPersistenceCapableClass().getName(),
addedSM.getPersistenceConfig().getPersistenceCapableClass().getName()));
}
| private java.lang.Object | addRelationship(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM)Updates the relationship field fieldDesc between this
and the state manager of the added object addedSM .
Object previousValue = null;
boolean isCollection = (fieldDesc.cardinalityUPB > 1);
if (!isCollection) {
previousValue = prepareSetField(fieldDesc, addedSM.persistentObject, true);
} else {
try {
prepareUpdateFieldSpecial(fieldDesc, null, true);
SCOCollection c = (SCOCollection) fieldDesc.getValue(this);
// Note: c might be null during relationship management for a
// self relationship, as in the Employee-Manager relation.
// See runtime test AutoPersistence.TestCase31 for an example.
if (c == null) {
replaceCollection(fieldDesc, null);
c = (SCOCollection) fieldDesc.getValue(this);
}
c.addInternal(addedSM.persistentObject);
updateTrackedFields(fieldDesc, c, null);
} catch (ClassCastException e) {
// ignore
}
}
return previousValue;
| private void | addUpdatedForeignReference(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager sm)Adds a dependency for state manager sm . State
manager sm must wait for this to be
flushed to the store before it can be written itself. State
manager sm is added to the list of objects
depending on this and will be notified when
this is written to the store. Store updates to
sm are disabled until then. This dependency is
established to maintain referential integrity conditions in the
data store.
// Avoid self-dependency.
if (sm == this) {
return;
}
// IMPORTANT: The following check assumes that this StateManager needs to be
// registered only if it has no updatedForeignReferences. Check if this causes
// a problem after this instance has been flushed, and updatedForeignReferences
// is now an empty collection.
if (updatedForeignReferences == null) {
updatedForeignReferences = new HashSet();
// Register this instance disregarding it's LifeCycle state.
// Otherwise, its state may never be reset after the transaction commits.
if ((stateFlags & ST_REGISTERED) == 0) {
persistenceManager.registerInstance(this, getObjectId(), false, true);
stateFlags |= ST_REGISTERED;
}
}
if (updatedForeignReferences.add(new UpdatedForeignReference(fieldDesc, sm))) {
sm.stateFlags |= ST_UPDATE_DISABLED;
sm.referenceCount++;
if (logger.isLoggable() ) {
String fieldName = (fieldDesc != null) ? fieldDesc.getName() : null;
Object[] items = new Object[] {this.persistentObject, fieldName,
sm.persistentObject, new Integer(sm.referenceCount)};
logger.fine("sqlstore.sqlstatemanager.addupdate", items); // NOI18N
}
// Register this instance disregarding it's LifeCycle state.
// Otherwise, its state may never be reset after the transaction commits.
if ((sm.stateFlags & ST_REGISTERED) == 0) {
persistenceManager.registerInstance(sm, sm.getObjectId(), false, true);
sm.stateFlags |= ST_REGISTERED;
}
}
| public void | applyUpdates(java.lang.String fieldName, SCOCollection c)This method is central to record changes to SCOCollections.
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.applyupdates", fieldName); // NOI18N
}
FieldDesc fieldDesc = persistenceConfig.getField(fieldName);
if (fieldDesc instanceof ForeignFieldDesc) {
ArrayList removed = new ArrayList(c.getRemoved());
ArrayList added = new ArrayList(c.getAdded());
// We reset the collection to clear the added and removed list before calling
// processCollectionUpdates() which can throw an exception.
c.reset();
processCollectionUpdates((ForeignFieldDesc) fieldDesc, removed, added, null, true, false);
}
// else it is an ERROR?
if (debug) {
logger.fine("sqlstore.sqlstatemanager.applyupdates.exit"); // NOI18N
}
| private void | assertNotPK(int fieldNumber)
if (persistenceConfig.isPKField(fieldNumber))
throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages,
"core.statemanager.nopkupdate")); // NOI18N
| private void | assertPKUpdate(FieldDesc f, java.lang.Object value)
Object currentValue = f.getValue(this);
boolean throwException = false;
// We only throw an exception if the new value is actually different from
// the current value.
if ((value != null) && (currentValue != null)) {
if (value.toString().compareTo(currentValue.toString()) != 0) {
throwException = true;
}
} else if (value != currentValue) {
throwException = true;
}
if (throwException) {
throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages,
"core.statemanager.nopkupdate")); // NOI18N
}
| private void | attachQueryResult(ForeignFieldDesc foreignField, java.util.Collection queryResult)Attaches the retrieved object(s) queryResult to the
relationship field foreignField of the instance
managed by this state manager.
assert foreignField != null;
// Attach the object(s) we got back to our managed object.
// There are three cases:
// 1) The foreign field contains a collection
// 2) The foreign object doesn't exist (NIL)
// 3) The foreign field is a reference to a single object
if (foreignField.getComponentType() != null) {
// Instantiate and populate a dynamic array, namely Collection.
// NOTE: queryResult is null, if we didn't execute the retrieval!
replaceCollection(foreignField, queryResult);
} else if (queryResult == null || queryResult.size() == 0) {
foreignField.setValue(this, null);
} else {
if (queryResult.size() > 1) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.persistencestore.toomanyobjforcard1", // NOI18N
persistenceConfig.getName(),
foreignField.getName(), "" + queryResult.size())); // NOI18N
}
Object v = queryResult.iterator().next();
foreignField.setValue(this, v);
}
| private static boolean | checkRelationship(com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager sm, ForeignFieldDesc fieldDesc, java.lang.Object pc)Checks, if there is a relationship between the persistence
capable instance managed by state manager sm and
pc on field fieldDesc . If
sm represents a before image, the relationship was
reset in the current transaction.
boolean related = false;
if (fieldDesc != null && sm != null
&& sm.getPresenceMaskBit(fieldDesc.absoluteID)) {
if (fieldDesc.cardinalityUPB > 1) {
// Checking directly for contains doesn't work for deferred SCOCollections.
Collection c = sm.getCollectionValue(fieldDesc);
// Resulting collection can't be null because the presence mask is set.
related = c.contains(pc);
} else {
related = fieldDesc.getValue(sm) == pc;
}
}
return related;
| private void | clearMask(int mask)
if (fieldMasks != null) {
fieldMasks.clear(mask * persistenceConfig.maxFields,
(mask+1) * persistenceConfig.maxFields);
}
| public java.lang.Object | clone()
SQLStateManager clone = new SQLStateManager(store, persistenceConfig);
clone.persistenceManager = persistenceManager;
return clone;
| private java.lang.Object | cloneObjectMaybe(java.lang.Object source)
// RESOLVE: need to clone SCOCollection
if (source != null) {
// RESOLVE: Should we clone byte[]???
if ((source instanceof SCO)) {
return ((SCO)source).cloneInternal();
} else if (!(source instanceof Number) &&
!(source instanceof String) &&
!(source instanceof Character) &&
!(source instanceof Boolean) &&
// RESOLVE: #javax.ejb package# !(source instanceof javax.ejb.EJBObject) &&
!(source instanceof com.sun.jdo.api.persistence.support.PersistenceCapable) &&
!(source instanceof byte[])) {
try {
Class type = source.getClass();
if (!type.isArray()) {
Method m = type.getMethod("clone", (Class []) null); // NOI18N
if (m != null) {
return m.invoke(source, (Object []) null);
}
} else {
Object srcArray[] = (Object[]) source;
Object dstArray[] = (Object[])
java.lang.reflect.Array.newInstance(type.getComponentType(), srcArray.length);
for (int i = 0; i < srcArray.length; i++) {
dstArray[i] = srcArray[i];
}
return dstArray;
}
} catch (NoSuchMethodException e) {
if (logger.isLoggable()) {
Object[] items = new Object[] {e, source.getClass().getName()};
logger.fine("sqlstore.sqlstatemanager.nosuchmethodexcep.clone", items); // NOI18N
}
} catch (InvocationTargetException e) {
} catch (IllegalAccessException e) {
}
}
}
return source;
| public void | commit(boolean retainValues)
boolean wasNew = (state.isNew() && !state.isDeleted());
state = state.transitionCommit(retainValues);
reset(retainValues, wasNew, false);
| private boolean | compareUpdatedFields(com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager next)
BitSet updFields = getVisibleMaskBits(SET_MASK);
BitSet nextUpdFields = (next != null) ? next.getVisibleMaskBits(SET_MASK) : null;
return updFields.equals(nextUpdFields);
| public void | copyFields(StateManager source)
if (!(source instanceof SQLStateManager)) {
String className =
(source != null) ? source.getClass().getName() : null;
throw new IllegalArgumentException(className);
}
SQLStateManager sqlSource = (SQLStateManager) source;
if (persistenceConfig != sqlSource.getPersistenceConfig()) {
Class thisPCClass =
persistenceConfig.getPersistenceCapableClass();
Class sourcePCClass =
sqlSource.getPersistenceConfig().getPersistenceCapableClass();
throw new IllegalArgumentException(
I18NHelper.getMessage(
messages,
"core.statemanager.copyFields.mismatch", // NOI18N
thisPCClass.getName(),
sourcePCClass.getName()));
}
copyFields(sqlSource, false, true);
| private void | copyFields(com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager source, boolean copyRelationships, boolean clone)
ArrayList fields = null;
// Reset the field masks, as the instance will
// be populated with the state from the source.
clearMask(PRESENCE_MASK);
clearMask(SET_MASK);
for (int i = 0; i < 2; i++) {
if (i == 0) {
fields = persistenceConfig.fields;
} else {
fields = persistenceConfig.hiddenFields;
}
for (int j = 0; (fields != null) && (j < fields.size()); j++) {
FieldDesc f = (FieldDesc) fields.get(j);
if (!copyRelationships && f.isRelationshipField()) {
continue;
}
if (source.getPresenceMaskBit(f.absoluteID)) {
Object value = f.getValue(source);
f.setValue(this, (clone) ? cloneObjectMaybe(value) : value);
setPresenceMaskBit(f.absoluteID);
}
}
}
| private com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager | copyPersistent()
PersistenceManager pm = (PersistenceManager) getPersistenceManagerInternal();
SQLStateManager newStateManager = (SQLStateManager) clone();
// Associate state manager with a new pc instance.
pm.newInstance(newStateManager);
newStateManager.copyFields(this, true, true);
return newStateManager;
| private void | copyValues(java.lang.Object[] values, LocalFieldDesc[] fields, int startIndex)Copies the value of fields into the array
values . The values are copied into the
array starting at index startIndex .
// The values array should be long enough to hold all the fields.
assert values.length - startIndex >= fields.length;
for (int i = 0; i < fields.length; i++) {
LocalFieldDesc field = fields[i];
values[i + startIndex] = field.getValue(this);
// The field is not expected to be null.
assert values[i + startIndex] != null;
}
| public void | deletePersistent()Prepares the associated object for delete. This method is
called by PersistenceManager.deletePersistent(). After
nullifying the relationship fields, the instance transitions to
deleted state.
if (logger.isLoggable()) {
logger.fine("sqlstore.sqlstatemanager.deletepersistence", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
// Why try try? The difference is in whether you try and then
// acquire/get, or acquire/get and then try.
// Prior to having acquireFieldUpdateLock, this code synchronized on
// a field, following that with the try for {get,release}Lock. That
// pattern of usage calls for that order.
// {acquire,release}FieldUpdateLock calls for the other order. We
// are close to FCS, so this strange situation persists for now
// (i.e., it ain't broken).
persistenceManager.acquireFieldUpdateLock();
try {
try {
getLock();
if (state.isDeleted()) {
return;
}
deleteRelationships();
LifeCycleState oldstate = state;
state = state.transitionDeletePersistent();
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
registerInstance(false, null, oldstate);
} finally {
releaseLock();
}
} finally {
persistenceManager.releaseFieldUpdateLock();
}
| private void | deleteRelationships()Prepares the current instance for delete by nullifying all
relationships. The deletion is propagated to relationship
fields marked for cascade delete.
ArrayList foreignFields = persistenceConfig.foreignFields;
int size = foreignFields.size();
stateFlags |= ST_DELETE_INPROGRESS;
for (int i = 0; i < size; i++) {
ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i);
ForeignFieldDesc irf = ff.getInverseRelationshipField();
// Skip this field if it is secondary.
if ((ff.sqlProperties & FieldDesc.PROP_SECONDARY_TRACKED_FIELD) > 0) {
continue;
}
// Skip this field if it is not managed nor marked for cascade delete.
if ((ff.deleteAction != ForeignFieldDesc.ACT_CASCADE) && (irf == null)) {
continue;
}
prepareUpdateField(ff, null);
if (ff.cardinalityUPB > 1) {
Collection c = (Collection) ff.getValue(this);
if (c != null) {
ArrayList removed = new ArrayList(c);
// For managed relationship or cascade delete, we need to call
// processCollectionUpdates() to set up the dependency. In case of
// managed relationship, the inverse relationship field should also
// be set to null.
processCollectionUpdates(ff, removed, null, null, true, false);
if (c instanceof SCOCollection) {
((SCOCollection) c).clearInternal();
} else {
c.clear();
}
if (ff.deleteAction == ForeignFieldDesc.ACT_CASCADE) {
Iterator iter = removed.iterator();
while (iter.hasNext()) {
Object obj = iter.next();
if (obj != null) {
SQLStateManager sm = (SQLStateManager)
persistenceManager.getStateManager(obj);
// Ignore if this sm is in the process of being cascade
// deleted. This is to prevent infinite recursive in case
// of self-referencing relationship.
if ((sm != null) && !sm.isDeleted() &&
((sm.stateFlags & ST_DELETE_INPROGRESS) == 0)) {
try {
persistenceManager.deletePersistent(obj);
} catch (Throwable e) {
}
}
}
}
}
}
} else {
Object obj = ff.getValue(this);
if (obj != null) {
updateObjectField(ff, null, true, false);
ff.setValue(this, null);
if (ff.deleteAction == ForeignFieldDesc.ACT_CASCADE) {
SQLStateManager sm = (SQLStateManager)
persistenceManager.getStateManager(obj);
// Ignore if this sm is in the process of being cascade
// deleted. This is to prevent infinite recursive in case
// of self-referencing relationships.
if ((sm != null) && !sm.isDeleted() &&
((sm.stateFlags & ST_DELETE_INPROGRESS) == 0)) {
try {
persistenceManager.deletePersistent(obj);
} catch (Throwable e) {
}
}
}
}
}
}
stateFlags &= ~ST_DELETE_INPROGRESS;
| private java.lang.Object | doUpdateField(FieldDesc fieldDesc, java.lang.Object value, boolean managedRelationshipInProgress)Sets field fieldDesc to value .
The update of relationship fields is triggered by either calling
{@link #updateCollectionField} or {@link #updateObjectField},
depending on the field's cardinality.
prepareUpdateField(fieldDesc, null);
if (fieldDesc instanceof ForeignFieldDesc) {
ForeignFieldDesc ff = (ForeignFieldDesc) fieldDesc;
if (ff.cardinalityUPB > 1) {
updateCollectionField(ff, (Collection) value,
managedRelationshipInProgress);
} else {
updateObjectField(ff, value, true,
managedRelationshipInProgress);
}
}
updateTrackedFields(fieldDesc, value, null);
Object currentValue = fieldDesc.getValue(this);
fieldDesc.setValue(this, value);
return currentValue;
| public void | flushed()
// reset the current state to the point where we can accept more updates.
state = state.transitionFlushed();
clearMask(SET_MASK);
stateFlags &= ~ST_VISITED;
stateFlags &= ~ST_UPDATE_DISABLED;
stateFlags &= ~ST_REGISTERED;
// need to set the jdoFlags to LOAD_REQUIRED to allow updated to be tracked.
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
if (updatedForeignReferences != null) {
updatedForeignReferences.clear();
}
if (updateDesc != null) {
updateDesc.reset();
}
| private com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager | getAddedSM(java.lang.Object addedObject, java.util.ArrayList newlyRegisteredSMs)Returns the added object's state manager. Transient objects become
"autopersistent" on the association to an already persistent instance and
are associated with a new state manager.
If newlyRegisteredSMs is not null, the newly created state manager
is added to the list. This list is only non-null for the treatment of deferred
collection fields, which is done before the actual flush to the data store.
Autopersistence management for all other cases is handled sufficiently
in the makeAutoPersistent call.
SQLStateManager addedSM = null;
if (addedObject != null) {
// Persistence by reachablity.
if ((addedSM = (SQLStateManager) persistenceManager.getStateManager(addedObject)) == null) {
makeAutoPersistent(addedObject);
addedSM = (SQLStateManager) persistenceManager.getStateManager(addedObject);
// Add the newly created state manager to the newlyRegisteredSMs
// list so we can do further processing on it.
if (newlyRegisteredSMs != null && !newlyRegisteredSMs.contains(addedSM)) {
newlyRegisteredSMs.add(addedSM);
}
}
}
return addedSM;
| public com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager | getBeforeImage()
// Do not try to get before image if not required
if (beforeImage == null && isBeforeImageRequired()) {
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.getbeforeimage", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
try {
getLock();
// Make a copy of the persistentObject.
beforeImage = copyPersistent();
} finally {
releaseLock();
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.getbeforeimage.exit"); // NOI18N
}
}
return beforeImage;
| private java.util.Collection | getCollectionValue(ForeignFieldDesc ff)Returns the value of the collection relationship field
ff . For deferred SCOCollections, only the
objects added in the current transaction are returned.
This method may only be called for Collection fields!
Collection c = null;
if (ff.cardinalityUPB > 1) {
c = (Collection) ff.getValue(this);
if (c != null && c instanceof SCOCollection) {
SCOCollection sco = (SCOCollection) c;
if (sco.isDeferred()) {
c = sco.getAdded();
}
}
}
return c;
| protected com.sun.jdo.spi.persistence.support.sqlstore.state.LifeCycleState | getCurrentState()For test purposes
return state;
| public java.lang.Object | getHiddenValue(int index)
// This method expects index to be negative for hidden fields.
if (index >= 0) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.poshiddenindex", "" + index)); // NOI18N
}
int realIndex = -(index + 1);
if ((hiddenValues != null) && (realIndex < hiddenValues.size())) {
return hiddenValues.get(realIndex);
}
return null;
| public void | getLock()Lock this instance.
lock.acquire();
| private java.lang.Object | getObjectById(ForeignFieldDesc ff, LocalFieldDesc updatedField, java.lang.Object value, boolean forNavigation)Looks up the object associated to this state manager on
relationship ff field in the persistence manager cache.
The method first constructs the related instance's object id by
calling {@link ForeignFieldDesc#createObjectId}. Then asks the
persistence manager to retrieve the object associated to this
id from it's caches. If the referred object is not found, the
instance returned by {@link PersistenceManager#getObjectById(Object)}
is Hollow. Hollow instances are ignored for navigation.
assert ff.cardinalityUPB <=1;
// If called for navigation updatedField and value should be null.
assert forNavigation ? updatedField == null && value == null : true;
Object rc = null;
Object oid = ff.createObjectId(this, updatedField, value);
if (oid != null) {
rc = persistenceManager.getObjectById(oid);
LifeCycleState rcState = ((SQLStateManager)
((PersistenceCapable) rc).jdoGetStateManager()).state;
if (forNavigation && (rcState instanceof Hollow)) {
rc = null;
}
}
return rc;
| public java.lang.Object | getObjectId()
// Note: PM.getObjectId() makes copy of the actual object id.
if (objectId == null) {
Class oidClass = persistenceConfig.getOidClass();
Object oid = null;
try {
oid = oidClass.newInstance();
} catch (Exception e) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.cantnewoid", oidClass.getName()), e); // NOI18N
}
Field keyFields[] = persistenceConfig.getKeyFields();
String keyFieldNames[] = persistenceConfig.getKeyFieldNames();
for (int i = 0; i < keyFields.length; i++) {
Field keyField = keyFields[i];
try {
FieldDesc fd = persistenceConfig.getField(keyFieldNames[i]);
if (fd != null) {
keyField.set(oid, fd.getValue(this));
}
} catch (IllegalAccessException e) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.cantsetkeyfield", keyField.getName()), e); // NOI18N
}
}
objectId = oid;
}
return objectId;
| public PersistenceConfig | getPersistenceConfig()
return persistenceConfig;
| public com.sun.jdo.api.persistence.support.PersistenceManager | getPersistenceManager()...
return (persistenceManager == null)? null : persistenceManager.getCurrentWrapper();
| public com.sun.jdo.api.persistence.support.PersistenceManager | getPersistenceManagerInternal()...
return persistenceManager;
| public java.lang.Object | getPersistent()
return persistentObject;
| public boolean | getPresenceMaskBit(int index)
if (fieldMasks == null) {
newFieldMasks();
}
if (index >= 0) {
return fieldMasks.get(index + PRESENCE_MASK * persistenceConfig.maxFields);
} else {
return fieldMasks.get(-(index + 1) + persistenceConfig.maxVisibleFields +
PRESENCE_MASK * persistenceConfig.maxFields);
}
| private com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager | getRemovedSM(java.lang.Object removedObject)Returns the removed object's state manager.
SQLStateManager removedSM = null;
if (removedObject != null) {
removedSM = (SQLStateManager) persistenceManager.getStateManager(removedObject);
}
return removedSM;
| public boolean | getSetMaskBit(int index)
if (fieldMasks == null) {
newFieldMasks();
}
if (index >= 0) {
return fieldMasks.get(index + SET_MASK * persistenceConfig.maxFields);
} else {
return fieldMasks.get(-(index + 1) + persistenceConfig.maxVisibleFields +
SET_MASK * persistenceConfig.maxFields);
}
| public PersistenceStore | getStore()
return store;
| private void | getUpdateActions(java.util.ArrayList actions)
if ((stateFlags & ST_VISITED) > 0) {
return;
}
int action = state.getUpdateAction();
if ((action == ActionDesc.LOG_NOOP) && (updateDesc == null)) {
return;
}
// Initialize updateDesc.
getUpdateDesc();
updateDesc.setObjectInfo(getBeforeImage(), this, action);
if ((action == ActionDesc.LOG_DESTROY) || (action == ActionDesc.LOG_CREATE) ||
updateDesc.hasUpdatedFields() || updateDesc.hasUpdatedJoinTableRelationships()) {
actions.add(updateDesc);
}
stateFlags |= ST_VISITED;
if (updatedForeignReferences != null) {
Iterator iter = updatedForeignReferences.iterator();
while (iter.hasNext()) {
SQLStateManager sm = ((UpdatedForeignReference) iter.next()).getStateManager();
if (sm.referenceCount == 1) {
sm.getUpdateActions(actions);
}
sm.referenceCount--;
}
}
| private com.sun.jdo.spi.persistence.support.sqlstore.sql.UpdateObjectDescImpl | getUpdateDesc()
if (updateDesc == null) {
updateDesc = (UpdateObjectDescImpl) store.getUpdateObjectDesc(
persistenceConfig.getPersistenceCapableClass());
}
if (updateDesc.getConcurrency() == null) {
boolean optimistic = persistenceManager.isOptimisticTransaction();
updateDesc.setConcurrency(persistenceConfig.getConcurrency(optimistic));
}
return updateDesc;
| private java.util.BitSet | getVisibleMaskBits(int mask)
if (fieldMasks == null) {
newFieldMasks();
}
int offset = mask * persistenceConfig.maxFields;
return fieldMasks.get(offset, offset + persistenceConfig.maxVisibleFields);
| public boolean | hasVersionConsistency()
return persistenceConfig.hasVersionConsistency();
| private static void | incrementVersion(java.util.List actions)Increments the version for all state managers in
actions registered for version consistency.
for (Iterator iter = actions.iterator(); iter.hasNext(); ) {
((UpdateObjectDescImpl) iter.next()).incrementVersion();
}
| public void | incrementVersion()Increments the version fields for this state manager. Instances
mapped to multiple tables have got a version field for each table.
LocalFieldDesc [] versionFields = persistenceConfig.getVersionFields();
for (int i = 0; i < versionFields.length; i++) {
versionFields[i].incrementValue(this);
}
| public synchronized void | initialize(boolean persistentInDB)
boolean xactActive = persistenceManager.isActiveTransaction();
boolean optimistic = persistenceManager.isOptimisticTransaction();
boolean nontransactionalRead = persistenceManager.isNontransactionalRead();
LifeCycleState oldstate = state;
if (state == null) {
if (persistentInDB == false) {
// Hollow object aquired by PM.getObjectByOid() does not require
// to be persistent in DB
state = LifeCycleState.getLifeCycleState(LifeCycleState.HOLLOW);
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
} else {
if (xactActive && !optimistic) {
state = LifeCycleState.getLifeCycleState(LifeCycleState.P_CLEAN);
persistenceManager.setFlags(persistentObject, READ_OK);
} else {
state = LifeCycleState.getLifeCycleState(LifeCycleState.P_NON_TX);
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
}
valid = true;
}
} else if (state.needMerge()) {
state = state.transitionReadField(optimistic, nontransactionalRead, xactActive);
// If we are in a state that requires the instance to be reloaded
// we need to set the jdoFlags to LOAD_REQUIRED to enable field mediation.
if (state.needsReload(optimistic, nontransactionalRead, xactActive)) {
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
} else {
if (persistenceManager.getFlags(persistentObject) == LOAD_REQUIRED) {
persistenceManager.setFlags(persistentObject, READ_OK);
}
}
}
registerInstance(false, null, oldstate);
| public boolean | isBeforeImageRequired()
com.sun.jdo.api.persistence.support.Transaction t = persistenceManager.currentTransaction();
// NOTE: We need to create a before image on relationship changes for two reasons:
// (1) Relationship management assumes relationship fields to be loaded.
// See prepareUpdateField.
// (2) The before image is used in realizeField.
boolean isBeforeImageRequired =
persistenceManager.isOptimisticTransaction() ||
getUpdateDesc().hasChangedRelationships() ||
t.getRetainValues() || t.getRestoreValues() ||
persistenceConfig.hasModifiedCheckAtCommitConsistency();
if (logger.isLoggable(Logger.FINER)) {
logger.finer("sqlstore.sqlstatemanager.isbeforeimagerequired", // NOI18N
Boolean.valueOf(isBeforeImageRequired));
}
return isBeforeImageRequired;
| public boolean | isDeleted()...
if (state != null) {
return state.isDeleted();
}
return false;
| public boolean | isDirty()...
if (state != null) {
return state.isDirty();
}
return false;
| public boolean | isNew()...
if (state != null) {
return state.isNew();
}
return false;
| public boolean | isPersistent()...
if (state != null) {
return state.isPersistent();
}
return false;
| public boolean | isProcessed()
return (referenceCount == 0);
| public boolean | isTransactional()...
if (state != null) {
return state.isTransactional();
}
return false;
| public boolean | isValid()Return value for valid flag.
return valid;
| public boolean | isVerificationFailed()
return (stateFlags & ST_VALIDATION_FAILED) > 0;
| public void | loadForRead()Triggers the state transition for READ and registers the
instance in the transaction cache.
boolean debug = logger.isLoggable(Logger.FINER);
if (debug) {
logger.finer("sqlstore.sqlstatemanager.loadforread"); // NOI18N
}
persistenceManager.acquireShareLock();
try {
getLock();
byte oldFlags = persistenceManager.getFlags(persistentObject);
// If the jdoFlag is either READ_OK or READ_WRITE_OK, that means another
// thread might have already call loadForRead on this instance.
if (oldFlags != LOAD_REQUIRED) {
return;
}
try {
boolean xactActive = persistenceManager.isActiveTransaction();
boolean optimistic = persistenceManager.isOptimisticTransaction();
boolean nontransactionalRead = persistenceManager.isNontransactionalRead();
if (state.needsReload(optimistic, nontransactionalRead, xactActive)) {
reload(null);
}
LifeCycleState oldstate = state;
state = state.transitionReadField(optimistic, nontransactionalRead, xactActive);
persistenceManager.setFlags(persistentObject, READ_OK);
registerInstance(false, null, oldstate);
} catch (JDOException e) {
// restore the jdoFlags.
persistenceManager.setFlags(persistentObject, oldFlags);
throw e;
}
} finally {
persistenceManager.releaseShareLock();
releaseLock();
if (debug) {
logger.finer("sqlstore.sqlstatemanager.loadforread.exit"); // NOI18N
}
}
| public void | loadForUpdate()Triggers the state transition for WRITE and registers the instance
in the transaction cache. Prepares all DFG fields for update.
boolean debug = logger.isLoggable(Logger.FINER);
if (debug) {
logger.finer("sqlstore.sqlstatemanager.loadforupdate"); // NOI18N
}
persistenceManager.acquireShareLock();
try {
getLock();
byte oldFlags = persistenceManager.getFlags(persistentObject);
// If the jdoFlags is already set to READ_WRITE_OK, it means that anther
// thread has called loadForUpdate on this instance.
if (oldFlags == READ_WRITE_OK) {
return;
}
persistenceManager.setFlags(persistentObject, READ_WRITE_OK);
ArrayList fields = persistenceConfig.fields;
try {
// Mark all the fields in the dfg dirty.
for (int i = 0; i < fields.size(); i++) {
FieldDesc f = (FieldDesc) fields.get(i);
if (f.fetchGroup == FieldDesc.GROUP_DEFAULT) {
//prepareSetField(f, null);
prepareUpdateField(f, null);
}
}
} catch (JDOException e) {
// restore the jdoFlags.
persistenceManager.setFlags(persistentObject, oldFlags);
throw e;
}
} finally {
persistenceManager.releaseShareLock();
releaseLock();
if (debug) {
logger.finer("sqlstore.sqlstatemanager.loadforupdate.exit"); // NOI18N
}
}
| private void | makeAutoPersistent(java.lang.Object pc)
persistenceManager.makePersistent(pc);
SQLStateManager sm = (SQLStateManager) persistenceManager.getStateManager(pc);
sm.state = LifeCycleState.getLifeCycleState(LifeCycleState.AP_NEW);
| public synchronized void | makeDirty(java.lang.String fieldName)
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.makedirty", fieldName); // NOI18N
}
FieldDesc fieldDesc = persistenceConfig.getField(fieldName);
// Save current value: if it is SCO object we need to replace it with the
// new value instead of new instance
Object oldo = fieldDesc.getValue(this);
prepareUpdateField(fieldDesc, null);
// Now adjust SCO instance
Object newo = fieldDesc.getValue(this);
if ((newo instanceof SCO) && oldo != newo) {
if (oldo instanceof SCOCollection) {
if (debug) {
logger.fine("sqlstore.sqlstatemanager.makedirty.fixscocollection"); // NOI18N
}
((SCOCollection) oldo).clearInternal();
((SCOCollection) oldo).addAllInternal((Collection) newo);
}
else if (oldo instanceof SCODate) {
if (debug) {
logger.fine("sqlstore.sqlstatemanager.makedirty.fixscodate"); // NOI18N
}
long l = ((java.util.Date) newo).getTime();
// Adjust nanoseconds if necessary:
int n = 0;
if (newo instanceof Timestamp) {
n = ((Timestamp) newo).getNanos();
} else {
n = (int) ((l % 1000) * 1000000);
}
if (oldo instanceof SqlTimestamp) {
((SCODate) oldo).setTimeInternal(l);
((SqlTimestamp) oldo).setNanosInternal(n);
} else if (newo instanceof Timestamp) {
((SCODate) oldo).setTimeInternal(l + (n / 1000000));
} else {
((SCODate) oldo).setTimeInternal(l);
}
}
updateTrackedFields(fieldDesc, oldo, null);
fieldDesc.setValue(this, oldo);
// disconnect temp SCO instance
if (newo instanceof SCO)
((SCO) newo).unsetOwner();
}
| public void | makePersistent(PersistenceManager pm, java.lang.Object pc)Prepares the associated object to be stored in the datastore.
This method is called by PersistenceManager.makePersistent().
Thread synchronization is done in the persistence manager.
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.makepersistence", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
// If the instance is autopersistent, we simply transition it to persistent_new.
if (state != null) {
if (state.isAutoPersistent()) {
state = state.transitionMakePersistent();
}
return;
}
this.persistenceManager = pm;
this.persistentObject = pc;
// Mark all the visible fields as present to prevent navigation and
// to allow us to create a before image that contains all the fields.
setVisibleMaskBits(PRESENCE_MASK);
getBeforeImage();
state = LifeCycleState.getLifeCycleState(LifeCycleState.P_NEW);
try {
registerInstance(true, null, null);
} catch (JDOException e) {
this.release();
throw e;
}
// We set the statemanager for the pc now so the instance is considered
// persistent. We need to do this in order for persistent-by-reachability to
// work properly in the case of self-referencing relationship.
pm.setStateManager(pc, this);
valid = true;
// Now that the state manager has been set in the pc, we need to
// synchronize it so other threads can't modify this instance while
// we perform the persistence-by-reachability algorithm.
try {
getLock();
// Make sure all the fields have been marked dirty.
Object obj = null;
ArrayList fields = persistenceConfig.fields;
for (int i = 0; i < fields.size(); i++) {
FieldDesc f = (FieldDesc) fields.get(i);
// In case of makePersistent, we skip all secondary tracked fields
// and use the primary to propagate changes. In addition, we take
// the policy that a tracked relationship field takes precedence
// over its primitive counterpart. In other words, we skip all
// primitive fields that also tracks relationship fields.
if ((f.sqlProperties & FieldDesc.PROP_SECONDARY_TRACKED_FIELD) > 0) {
continue;
}
obj = f.getValue(this);
if (f instanceof ForeignFieldDesc) {
ForeignFieldDesc ff = (ForeignFieldDesc) f;
ArrayList trackedFields = null;
if (debug) {
logger.fine("sqlstore.sqlstatemanager.processforeign", ff.getName()); // NOI18N
}
if ((ff.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) > 0) {
trackedFields = ff.getTrackedFields();
Object theValue = obj;
for (int j = 0; j < trackedFields.size(); j++) {
FieldDesc tf = (FieldDesc) trackedFields.get(j);
Object value = tf.getValue(this);
if ((theValue != null) && (value != null) && (theValue != value)) {
if (needsVerifyAtDeregister) {
persistenceManager.deregisterInstance(getObjectId(), this);
needsVerifyAtDeregister = false;
} else {
persistenceManager.deregisterInstance(getObjectId());
}
this.release();
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.statemanager.conflictingvalues", ff.getName(), tf.getName())); // NOI18N
} else if ((theValue == null) && (value != null)) {
theValue = value;
}
}
if (theValue != obj) {
obj = theValue;
ff.setValue(this, obj);
}
}
if (obj != null) {
if (obj instanceof Collection) {
if (((Collection) obj).size() > 0) {
ArrayList removed = null;
ArrayList added = new ArrayList((Collection) obj);
processCollectionUpdates(ff, removed, added, null, true, false);
}
} else {
// null out this field to pretend we are setting this field for the first time
ff.setValue(this, null);
updateObjectField(ff, obj, true, false);
// now restore the value
ff.setValue(this, obj);
}
} else {
// For a null managed collection relationship field, we replace it
// with an empty SCOCollection
if ((ff.getInverseRelationshipField() != null) && (ff.cardinalityUPB > 1)) {
replaceCollection(ff, null);
}
}
updateTrackedFields(ff, ff.getValue(this), null);
} else {
// We ignore primitive fields that also tracks relationship field
if ((f.sqlProperties & FieldDesc.PROP_TRACK_RELATIONSHIP_FIELD) > 0) {
ArrayList trackedFields = f.getTrackedFields();
boolean found = false;
for (int j = trackedFields.size() - 1; j >= 0; j--) {
FieldDesc tf = (FieldDesc) trackedFields.get(j);
if (tf instanceof ForeignFieldDesc) {
if (tf.getValue(this) != null) {
found = true;
break;
}
} else {
break;
}
}
if (!found) {
//f.setValue(this, null);
updateTrackedFields(f, obj, null);
//f.setValue(this, obj);
}
} else {
updateTrackedFields(f, obj, null);
}
if ((f.sqlProperties & FieldDesc.PROP_RECORD_ON_UPDATE) > 0) {
getUpdateDesc().recordUpdatedField((LocalFieldDesc) f);
}
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.makedirtyfield", f.getName()); // NOI18N
}
setSetMaskBit(f.absoluteID);
}
} finally {
releaseLock();
}
| public void | makePresent(java.lang.String fieldName, java.lang.Object value)
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.makepresent", fieldName); // NOI18N
}
FieldDesc fieldDesc = persistenceConfig.getField(fieldName);
fieldDesc.setValue(this, value);
setPresenceMaskBit(fieldDesc.absoluteID);
| private void | manageDependencyForObjectField(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedInverseFieldSM)Dependency management for database operations on the one-to-one
relationships. Establishes a dependency to nullify the foreign key on the
removed instance before the added instance's foreign key can be set. If
the relationship is mapped to a jointable, remove the jointable entry to
the removed instance before the jointable entry on the added can be
added. This update dependency is valid only for one-to-one relationships,
because only one-to-one relationships can be enforced by an unique
index on the foreign key. On the other hand, there's never a state
manager removed from the relationship for one-to-many relationships.
We would like to do this in updateRelationshipInDataStore,
but we don't know the added instance's previous value in case of
updateOtherSide == false there. Here, we can handle this situation
at one place.
// If the fieldDesc property has the REF_INTEGRITY_UPDATES unset,
// it means data store updates are scheduled on the other side of the relationship.
boolean updateOtherSide = (fieldDesc.sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0;
// Nullify the foreign key on the removed object before
// the added object's foreign key can be set.
if (updateOtherSide && removedSM != null && addedSM != null) {
// Add the dependency only if both objects involved
// in the relationship being removed are already persistent.
if (removedSM.state.isPersistentInDataStore()
&& this.state.isPersistentInDataStore()) {
// First parameter == null marks a non removable dependency.
// RESOLVE: Pass inverseFieldDesc here.
removedSM.addUpdatedForeignReference(null, addedSM);
}
}
// If the foreign key is on this side, addedInverseFieldSM
// corresponds to the removedSM and this is the addedSM!
if (!updateOtherSide && addedInverseFieldSM != null) {
// Add the dependency only if both objects involved
// in the relationship being removed are already persistent.
if (addedInverseFieldSM.state.isPersistentInDataStore()
&& addedSM.state.isPersistentInDataStore()) {
// First parameter == null marks a non removable dependency.
// RESOLVE: Pass inverseFieldDesc here.
addedInverseFieldSM.addUpdatedForeignReference(null, this);
}
}
| private com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager | manageRelationshipForObjectField(ForeignFieldDesc inverseFieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, boolean managedRelationshipInProgress)Updates the (inverse) relationship field for addedSM
and removedSM .
Object addedInverseFieldValue = null;
SQLStateManager addedInverseFieldSM = null;
if (removedSM != null) {
removedSM.removeRelationship(inverseFieldDesc, this);
}
if (addedSM != null && !managedRelationshipInProgress) {
addedInverseFieldValue = addedSM.addRelationship(inverseFieldDesc, this);
if (addedInverseFieldValue != null) {
addedInverseFieldSM = (SQLStateManager)
persistenceManager.getStateManager(addedInverseFieldValue);
}
}
return addedInverseFieldSM;
| private void | markKeyFieldsPresent()
ArrayList keyFields = persistenceConfig.getPrimaryTable().getKey().getFields();
for (int i = 0; i < keyFields.size(); i++) {
LocalFieldDesc fd = (LocalFieldDesc) keyFields.get(i);
if (fd != null) {
setPresenceMaskBit(fd.absoluteID);
}
}
| public void | markNotRegistered()Marks this instance needs to require registering with the global (weak) cache
at rollback if it transitions to persistent state.
Used for replacing a deleted instance with the newly persistent with
the same object id.
needsRegisterAtRollback = true;
| public void | markReplacement()Marks this instance as a replacement for a deleted instance with the same
ObjectId.
isReplacementInstance = true;
| public void | markVerifyAtDeregister()Marks this instance as needs to be verified at the time it is removed from the
global (weak) cache at rollback if it transitions to transient state.
needsVerifyAtDeregister = true;
| public boolean | needsRegisterWithVersionConsistencyCache()
boolean rc = hasVersionConsistency();
if (rc && state != null) {
rc = state.isPersistent()
&& state.isTransactional()
&& !state.isNew()
&& !state.isDirty()
&& !state.isDeleted();
}
return rc;
| public boolean | needsUpdateInVersionConsistencyCache()
boolean rc = hasVersionConsistency();
if (rc && state != null) {
rc = (state.isDirty()
|| state.isNew()
|| persistenceConfig.hasLocalNonDFGFields())
&& !state.isDeleted();
}
return rc;
| private void | newFieldMasks()
this.fieldMasks = new BitSet(MAX_MASKS * persistenceConfig.maxFields);
| private void | nullifyForeignKey(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, ForeignFieldDesc inverseFieldDesc, boolean setDependencyOnly)Nullifies the (hidden) local fields corresponding to the foreign key columns
for relationship field fieldDesc . Usually the foreign key
columns are not mapped explicitly by the user. For this reason the runtime
creates hidden fields representing the foreign key columns internally. We
determine the local fields by iterating appropriate field list of either
fieldDesc or inverseFieldDesc .
For dependency management, the removal of the foreign key has
to be nullified before the _possible_ removal of removedSM. The
same dependency applies to jointable relationships, see {@link
#registerRemoveDependency}.
if (!isDeleted() && !setDependencyOnly) {
// fieldDesc can be null for one-directional relationships. We are
// only interested in the LocalFieldDescs for the foreign key columns,
// which can also be retrieved from inverseFieldDesc.
if (fieldDesc != null) {
for (int i = 0; i < fieldDesc.localFields.size(); i++) {
LocalFieldDesc la = (LocalFieldDesc) fieldDesc.localFields.get(i);
nullifyForeignKey(fieldDesc, la);
}
} else {
for (int i = 0; i < inverseFieldDesc.foreignFields.size(); i++) {
LocalFieldDesc la = (LocalFieldDesc) inverseFieldDesc.foreignFields.get(i);
nullifyForeignKey(fieldDesc, la);
}
}
}
// Nullify the foreign key before the _possible_ removal of removedSM.
registerRemoveDependency(fieldDesc, removedSM);
| private void | nullifyForeignKey(ForeignFieldDesc fieldDesc, LocalFieldDesc la)Actually nullifies the local field la corresponding to a
foreign key column for the relationship update.
Fields tracking the foreign key field la are updated.
if (!getSetMaskBit(la.absoluteID)) {
prepareUpdateField(la, null);
}
JDOUserException pkUpdateEx = null;
if (la.isKeyField()) {
try {
assertPKUpdate(la, null);
} catch (JDOUserException e) {
// If the relationship being set to null
// and the parent instance is being deleted, we will ignore
// the exception thrown from assertPKUpdate(). The reason is
// that we are really just trying to set up the dependency
// and not modify the relationship itself. If we do not
// ignore this exception, there will be no way to delete
// the parent instance at all because we don't support
// modifying primary key.
if (((stateFlags & ST_DELETE_INPROGRESS) == 0)) {
throw e;
}
pkUpdateEx = e;
}
}
if (pkUpdateEx == null) {
// As la tracks fieldDesc, fieldDesc is ignored in updateTrackedFields.
updateTrackedFields(la, null, fieldDesc);
la.setValue(this, null);
}
| private void | populateForeignField(ForeignFieldDesc foreignField)Retrieves the relationship.
assert foreignField != null;
boolean foundInstance = false;
if (foreignField.hasForeignKey() && foreignField.isMappedToPk()) {
// Cache lookup, returns an object.
Object pc = getObjectById(foreignField, null, null, true);
if (foundInstance = (pc != null)) {
foreignField.setValue(this, pc);
}
}
if (!foundInstance) {
// Query lookup, returns a collection.
Collection result = retrieveForeign(foreignField);
attachQueryResult(foreignField, result);
}
// Or in PRESENT bit for this field in the properties mask
setPresenceMaskBit(foreignField.absoluteID);
| public void | prepareGetField(int fieldID)
FieldDesc fieldDesc = persistenceConfig.getField(fieldID);
prepareGetField(fieldDesc, false, true);
| private void | prepareGetField(FieldDesc fieldDesc)
prepareGetField(fieldDesc, true, false);
| private void | prepareGetField(FieldDesc fieldDesc, boolean internal, boolean acquireShareLock)Loads the field described by fieldDesc . If the field is not
present in the instance, it will be loaded from the data store by calling
{@link #realizeField(FieldDesc)}. Depending on its lifecycle state,
the instance is registered in the transaction cache and the field
is marked as read.
boolean debug = logger.isLoggable(Logger.FINEST);
if (debug) {
logger.finest("sqlstore.sqlstatemanager.preparegetfield", fieldDesc.getName()); // NOI18N
}
if (acquireShareLock) {
persistenceManager.acquireShareLock();
}
try {
getLock();
boolean xactActive = persistenceManager.isActiveTransaction();
boolean optimistic = persistenceManager.isOptimisticTransaction();
boolean nontransactionalRead = persistenceManager.isNontransactionalRead();
if (state.needsReload(optimistic, nontransactionalRead, xactActive)) {
reload(fieldDesc);
}
LifeCycleState oldstate = state;
state = state.transitionReadField(optimistic, nontransactionalRead, xactActive);
registerInstance(false, null, oldstate);
// Only allow dynamic navigation if we are not in the state that allows it.
if (state.isNavigable() || !internal) {
if (getPresenceMaskBit(fieldDesc.absoluteID) == false) {
realizeField(fieldDesc);
}
}
} catch (JDOException e) {
throw e;
} catch (Exception e) {
logger.log(Logger.FINE,"sqlstore.exception.log", e);
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.getfieldfailed"), e); // NOI18N
} finally {
if (acquireShareLock) {
persistenceManager.releaseShareLock();
}
releaseLock();
if (debug) {
logger.finest("sqlstore.sqlstatemanager.preparegetfield.exit"); // NOI18N
}
}
| private java.lang.Object | prepareSetField(int fieldID, java.lang.Object value)
FieldDesc fieldDesc = persistenceConfig.getField(fieldID);
return prepareSetField(fieldDesc, value, false, true);
| private java.lang.Object | prepareSetField(FieldDesc fieldDesc, java.lang.Object value)
return prepareSetField(fieldDesc, value, false, false);
| private java.lang.Object | prepareSetField(FieldDesc fieldDesc, java.lang.Object value, boolean managedRelationshipInProgress)Internal method setting the new value value for field
fieldDesc during relationship management. Only called on
relationship additions for object fields. This method is never called
for collection fields. Relationship management for collection fields
is done by deferred collections in {@link #addRelationship}.
Deferred collections are implemented in SCOCollection .
Relationship management on relationship removal is done in
{@link #removeRelationship} for both object and collection fields.
return prepareSetField(fieldDesc, value, managedRelationshipInProgress, false);
| private java.lang.Object | prepareSetField(FieldDesc fieldDesc, java.lang.Object value, boolean managedRelationshipInProgress, boolean acquireShareLock)Sets field fieldDesc by calling
{@link SQLStateManager#doUpdateField(FieldDesc, Object, boolean)}.
boolean debug = logger.isLoggable(Logger.FINEST);
if (debug) {
logger.finest("sqlstore.sqlstatemanager.preparesetfield", fieldDesc.getName()); // NOI18N
}
if (acquireShareLock) {
persistenceManager.acquireShareLock();
}
try {
getLock();
if ((fieldDesc.sqlProperties & FieldDesc.PROP_READ_ONLY) > 0) {
throw new JDOUserException(I18NHelper.getMessage(messages,
"core.statemanager.readonly", fieldDesc.getName(), // NOI18N
persistentObject.getClass().getName()));
}
// We need to lock fieldUpdateLock if there is a chance that
// relationship field values might be affected. This is the case if
// fieldDesc is a relationship field or it tracks other fields.
if ((fieldDesc.getTrackedFields() != null) ||
(fieldDesc instanceof ForeignFieldDesc)) {
persistenceManager.acquireFieldUpdateLock();
try {
return doUpdateField(fieldDesc, value, managedRelationshipInProgress);
} finally {
persistenceManager.releaseFieldUpdateLock();
}
} else {
return doUpdateField(fieldDesc, value, managedRelationshipInProgress);
}
} catch (JDOException e) {
throw e;
} catch (Exception e) {
logger.log(Logger.FINE,"sqlstore.exception.log", e);
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.setfieldfailed"), e); // NOI18N
} finally {
if (acquireShareLock) {
persistenceManager.releaseShareLock();
}
releaseLock();
if (debug) {
logger.finest("sqlstore.sqlstatemanager.preparesetfield.exit"); // NOI18N
}
}
| public void | prepareToUpdatePhaseI()PersistenceManager calls this method to prepare a persistent
object for update. This is required for foreign fields only
as they could reference "regular" JDK Collections vs. SCO
Collections. Such process has the side-effect of causing more
objects to be registered with the transaction cache.
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.preparetoupdateph1", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
int action = state.getUpdateAction();
if (action == ActionDesc.LOG_NOOP || action == ActionDesc.LOG_DESTROY) {
// Nothing extra to do
return;
}
// Initialize UpdateDesc.
getUpdateDesc();
ArrayList newlyRegisteredSMs = new ArrayList();
ArrayList foreignFields = persistenceConfig.foreignFields;
int size = foreignFields.size();
for (int i = 0; i < size; i++) {
ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i);
if ((ff.sqlProperties & FieldDesc.PROP_SECONDARY_TRACKED_FIELD) > 0) {
continue;
}
if ((ff.cardinalityUPB > 1) && (getSetMaskBit(ff.absoluteID) == true)) {
Collection v = (Collection) ff.getValue(this);
if ((v != null) && (!(v instanceof SCO) || (((SCO) v).getOwner() == null)) &&
(v.size() > 0)) {
ArrayList removed = null;
ArrayList added = new ArrayList(v);
processCollectionUpdates(ff, removed, added, newlyRegisteredSMs, true, false);
}
}
}
// The newRegisteredSMs should contain a list of all the state managers that
// are registered as the result of processCollectionUpdates.
for (int i = 0; i < newlyRegisteredSMs.size(); i++) {
SQLStateManager sm = (SQLStateManager) newlyRegisteredSMs.get(i);
sm.prepareToUpdatePhaseI();
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.preparetoupdateph1.exit"); // NOI18N
}
| public void | prepareToUpdatePhaseII(java.util.HashSet phase3sms)This is the second phase of the commit processing. It populates phase3sms with all
the autopersistent instances that are no longer reachable from a persistent instance.
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.preparetoupdateph2", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
// If this instance is autopersistent, we transition it into a pending state and
// add it to phase3sms collection. Any instance in phase3sms collection may be removed
// later if it becomes persistent.
if (state.isAutoPersistent()) {
state = state.transitionMakePending();
phase3sms.add(this);
return;
}
if ((stateFlags & ST_PREPARED_PHASE_II) > 0) {
return;
}
stateFlags |= ST_PREPARED_PHASE_II;
if ((!state.isNew() && !state.isDirty()) || state.isDeleted()) {
return;
}
ArrayList foreignFields = persistenceConfig.foreignFields;
int size = foreignFields.size();
// Walk the object graph starting from this instance and transition all
// autopersistent instances to persistent and remove it from phase3sms.
for (int i = 0; i < size; i++) {
ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i);
if (ff.cardinalityUPB <= 1) {
if (getPresenceMaskBit(ff.absoluteID)) {
Object v = ff.getValue(this);
if (v != null) {
transitionPersistent(v, phase3sms);
}
}
} else {
Collection c = getCollectionValue(ff);
if (c != null) {
Iterator iter = c.iterator();
while (iter.hasNext()) {
Object v = iter.next();
transitionPersistent(v, phase3sms);
}
}
}
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.preparetoupdateph2.exit"); // NOI18N
}
| public void | prepareToUpdatePhaseIII()This is the third phase of commit processing. It sets up the delete dependencies among
all the autopersistent instances that have been flushed to the database.
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.preparetoupdateph3", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
if (!state.isPersistentInDataStore()) {
// This object will not be written to the store. But we need to
// make sure, that scheduled jointable entries aren't written either.
// See UpdateQueryPlan#processJoinTables().
if (updateDesc != null) {
updateDesc.clearUpdatedJoinTableRelationships();
}
// Finished for this instance.
return;
}
ArrayList foreignFields = persistenceConfig.foreignFields;
int size = foreignFields.size();
// Sets up dependencies between this instance and all its relationship fields
// that are autopersistent.
for (int i = 0; i < size; i++) {
ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i);
if (ff.cardinalityUPB <= 1) {
if (getPresenceMaskBit(ff.absoluteID)) {
Object v = ff.getValue(this);
if (v != null) {
updateObjectField(ff, null, false, false);
}
}
} else {
Collection c = getCollectionValue(ff);
if (c != null) {
if (c.size() > 0) {
ArrayList removed = new ArrayList(c);
ArrayList added = null;
processCollectionUpdates(ff, removed, added, null, false, false);
}
}
}
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.preparetoupdateph3.exit"); // NOI18N
}
| private void | prepareUpdateField(FieldDesc fieldDesc, java.util.ArrayList newlyRegisteredSMs)Prepares the field described by fieldDesc for update.
This method is central to record changes to fields. The state
transitions to dirty. The instance is registered in the
transaction cache. If the field is set for the first time,
the before image is prepared and the field is marked as modified.
Updated local fields are added to the column list to be updated.
// No updates for key fields. As this method is called by
// loadForUpdate for _all_ DFG fields (to prepare a hollow
// instance for update), we can't throw an exception here
// like in prepareUpdateFieldSpecial.
if (fieldDesc.isKeyField()) {
return;
}
getUpdateDesc().markRelationshipChange(fieldDesc);
boolean debug = logger.isLoggable();
if (debug) {
Object[] items = new Object[] {fieldDesc.getName(),state};
logger.fine("sqlstore.sqlstatemanager.prepareupdatefield", items); // NOI18N
}
boolean optimistic = persistenceManager.isOptimisticTransaction();
boolean xactActive = persistenceManager.isActiveTransaction();
boolean nontransactionalRead = persistenceManager.isNontransactionalRead();
if (state.needsReload(optimistic, nontransactionalRead, xactActive)) {
reload(fieldDesc);
}
// State transition.
// The state transition prevends field updates on deleted instances
// and must always be executed. See PersistentDeleted.transitionWriteField().
LifeCycleState oldstate = state;
state = state.transitionWriteField(xactActive);
registerInstance(false, newlyRegisteredSMs, oldstate);
if (state == oldstate && getSetMaskBit(fieldDesc.absoluteID) &&
getPresenceMaskBit(fieldDesc.absoluteID)) {
// The presence mask bit is NEVER set for deferred collections,
// because deferred collections MUST always be reloaded.
return;
}
// We don't reload the field for a newly created instance.
if (state.isBeforeImageUpdatable()) {
// Reload the field, as relationship management
// assumes that relationship fields are always present.
// See updateObjectField() or processCollectionupdates().
if (!getPresenceMaskBit(fieldDesc.absoluteID)) {
prepareGetField(fieldDesc);
}
updateBeforeImage(fieldDesc, null);
}
recordUpdatedField(fieldDesc);
if (debug) {
logger.fine("sqlstore.sqlstatemanager.prepareupdatefield.exit"); // NOI18N
}
| private synchronized void | prepareUpdateFieldSpecial(FieldDesc fieldDesc, java.lang.Object beforeImageValue, boolean createDeferredCollection)This is a special version of prepareUpdateField that does not do navigation
if a field is not loaded. We don't need to reload the field, because the
before image value is given as parameter! This method is mostly called
during relatioship management, as the before image value is already know
in this case.
The createDeferredCollection parameter should be true
only if fieldDesc corresponds to a collection field. Note:
createDeferredCollection == false
==> beforeImageValue must be non-null.
createDeferredCollection == true
==> beforeImageValue is null.
.
if (fieldDesc.isKeyField()) {
throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages,
"core.statemanager.nopkupdate")); // NOI18N
}
getUpdateDesc().markRelationshipChange(fieldDesc);
boolean debug = logger.isLoggable();
if (debug) {
Object[] items = new Object[] {fieldDesc.getName(),state};
logger.fine("sqlstore.sqlstatemanager.prepareupdatefieldspl", items); // NOI18N
}
boolean optimistic = persistenceManager.isOptimisticTransaction();
boolean xactActive = persistenceManager.isActiveTransaction();
boolean nontransactionalRead = persistenceManager.isNontransactionalRead();
if (state.needsReload(optimistic, nontransactionalRead, xactActive)) {
if (!optimistic) {
persistenceManager.clearFields(this.persistentObject);
}
reload(null);
}
LifeCycleState oldstate = state;
state = state.transitionWriteField(xactActive);
registerInstance(false, null, oldstate);
if (getSetMaskBit(fieldDesc.absoluteID)) {
// Note: The set mask is set for all fields on make persistent.
return;
}
if (!getPresenceMaskBit(fieldDesc.absoluteID)) {
if (!createDeferredCollection) {
if (!(beforeImageValue instanceof SCOCollection) ||
!((SCOCollection) beforeImageValue).isDeferred()) {
updateBeforeImage(fieldDesc, beforeImageValue);
// Set the presence mask for a non deferred collection.
setPresenceMaskBit(fieldDesc.absoluteID);
}
} else {
// Deferred collection handling.
if (!(fieldDesc instanceof ForeignFieldDesc) ||
(((ForeignFieldDesc) fieldDesc).cardinalityUPB <= 1)) {
//should throw an exception
return;
}
Object value = fieldDesc.getValue(this);
if (value == null) {
// If the collection field is null, we need to create a
// deferred SCOCollection.
SCOCollection c = (SCOCollection) persistenceManager.newCollectionInstanceInternal(
fieldDesc.getType(),
persistentObject,
fieldDesc.getName(),
fieldDesc.getComponentType(),
false,
10);
c.markDeferred();
fieldDesc.setValue(this, c);
}
// NOTE: We don't set the presence mask bit for deferred collections,
// because deferred collections MUST be reloaded on the first read access!
}
}
recordUpdatedField(fieldDesc);
if (debug) {
logger.fine("sqlstore.sqlstatemanager.prepareupdatefieldspl.exit"); // NOI18N
}
| private void | processCollectionUpdates(ForeignFieldDesc fieldDesc, java.util.ArrayList removedList, java.util.ArrayList addedList, java.util.ArrayList newlyRegisteredSMs, boolean updateInverseRelationshipField, boolean managedRelationshipInProgress)Updates the relationship for the collection side of a one-to-many or
many-to-many relationship. Objects in removedList are
removed from the relation. The relation is set on all objects in
addedList . In case of user updates, relationship management
on "this" relationship side is done by the user, i.e. by
d.getEmployees().add(newEmp) for a Department d. This method is never
called during relationship management.
boolean debug = logger.isLoggable();
ForeignFieldDesc inverseFieldDesc = fieldDesc.getInverseRelationshipField();
// RESOLVE: What if
// * inverseFieldDesc is null?
// * fieldDesc.cardinalityUPB == 1
if (debug) {
Object[] items = new Object[] {removedList,addedList};
logger.fine("sqlstore.sqlstatemanager.processcollectionupdate", items); // NOI18N
}
// removedList contains the list of objects removed.
if (removedList != null) {
removeCollectionRelationship(fieldDesc, removedList, inverseFieldDesc,
updateInverseRelationshipField, managedRelationshipInProgress);
}
// addedList contains the objects added.
if (addedList != null) {
addCollectionRelationship(fieldDesc, addedList, inverseFieldDesc,
newlyRegisteredSMs,
updateInverseRelationshipField, managedRelationshipInProgress);
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.processcollectionupdate.exit"); // NOI18N
}
| private void | processForeignKeys(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, ForeignFieldDesc inverseFieldDesc, boolean managedRelationshipInProgress)Updates the (hidden) local fields corresponding to the foreign key columns
if the relationship is mapped to a foreign key. The updates are written
to the store when the instance is flushed. For relationships mapped to
foreign keys, we always update the side with the foreign key.
The collection side never has the foreign key. Data store updates for
added objects are not processed twice during relationship management.
Data store dependencies for the update operations are established.
// If the fieldDesc property has the REF_INTEGRITY_UPDATES unset, it means we
// need to update the other side of the relationship naming the foreign key fields.
boolean updateOtherSide = (fieldDesc.sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0;
if (updateOtherSide) {
// Null out the foreign key on the removed object.
if (removedSM != null) {
removedSM.nullifyForeignKey(inverseFieldDesc, this, fieldDesc, false);
}
// Set the foreign key on the added object.
// Don't set the fk twice during relationship management.
if (addedSM != null && !managedRelationshipInProgress) {
addedSM.setForeignKey(inverseFieldDesc, this, fieldDesc);
}
} else {
// Null out the foreign key to the removed object.
if (removedSM != null) {
// Don't overwrite the foreign key, if both removedSM and
// addedSM != null. See runtime test rel12 for an example.
nullifyForeignKey(fieldDesc, removedSM, inverseFieldDesc, addedSM != null);
}
// Set the foreign key to the added object.
// Don't set the fk twice during relationship management.
if (addedSM != null && !managedRelationshipInProgress) {
// See above!
setForeignKey(fieldDesc, addedSM, inverseFieldDesc);
}
}
| private void | processJoinTableEntries(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, ForeignFieldDesc inverseFieldDesc, boolean managedRelationshipInProgress)Schedules jointable entries for relationships mapped to jointables.
The actual creation/removal of the jointable entry is deferred until
flush. Data store updates for added objects are not processed twice
during relationship management.
Data store dependencies for the update operations are established.
// If the fieldDesc property has the REF_INTEGRITY_UPDATES unset,
// it means we need to update the other side of the relationship.
boolean updateOtherSide = (fieldDesc.sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0;
if (updateOtherSide) {
// Schedule the removal of the jointable entry to removedSM.
if (removedSM != null) {
removedSM.removeJoinTableEntry(inverseFieldDesc, this, fieldDesc);
}
// Schedule the jointable entry to the added object.
// Don't schedule the jointable entry twice during relationship management.
if (addedSM != null && !managedRelationshipInProgress) {
addedSM.addJoinTableEntry(inverseFieldDesc, this, fieldDesc);
}
} else {
// Schedule the removal of the jointable entry to removedSM.
if (removedSM != null) {
// Contrary to foreign key relationships, we always have
// to remove the previous jointable entry.
removeJoinTableEntry(fieldDesc, removedSM, inverseFieldDesc);
}
// Schedule the jointable entry to the added object.
// Don't schedule the jointable entry twice during relationship management.
if (addedSM != null && !managedRelationshipInProgress) {
addJoinTableEntry(fieldDesc, addedSM, inverseFieldDesc);
}
}
| private void | realizeField(FieldDesc fieldDesc)Retrieves a field specified by fieldDesc from the data
store. If the field is part of a group then all unfetched fields
in the group are retrieved. realizeField is part of dynamic
navigation. The field is marked as present.
assert fieldDesc != null;
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.realizefield", fieldDesc.getName()); // NOI18N
}
if (!persistenceConfig.isNavigable()) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.notnavigable", // NOI18N
fieldDesc.getName(), persistentObject.getClass().getName()));
}
boolean fieldRealized = false;
if (fieldDesc instanceof ForeignFieldDesc) {
ForeignFieldDesc ff = (ForeignFieldDesc) fieldDesc;
// We can do an enhancement if we are only getting a single
// relationship field. Check if the field can be retrieved on
// it's own and the relationship is not mapped to a join table.
// The field can be retrieved on it's own if it's is in
// an independent fetch group or not in a fetch group at all.
// Independent fetch groups have group ids < FieldDesc.GROUP_NONE.
if (ff.fetchGroup <= FieldDesc.GROUP_NONE
&& persistenceConfig.getFetchGroup(ff.fetchGroup).size() <= 1
&& !ff.useJoinTable()) {
fieldRealized = realizeForeignField(ff);
}
}
if (!fieldRealized) {
retrieve(fieldDesc);
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.realizefield.exit"); // NOI18N
}
| private boolean | realizeForeignField(ForeignFieldDesc foreignField)For foreign fields we want to take advantage of knowing the
relationship key and only selecting the foreign rather than the
primary with the foreign attached. Most of the work is in
figuring out whether we can do that.
assert foreignField != null;
boolean isPresent = false;
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.realizeforeignfield", // NOI18N
foreignField.getName());
}
// Check and see if all the values we need are present.
for (int i = 0; i < foreignField.localFields.size(); i++) {
LocalFieldDesc lf = (LocalFieldDesc) foreignField.localFields.get(i);
isPresent = getPresenceMaskBit(lf.absoluteID);
if (!isPresent) {
break;
}
}
if (isPresent) {
// All the values we need are present. Wow. Now we'll have to
// format a more specialized request and attach the object(s)
// we get back to our managed object.
populateForeignField(foreignField);
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.realizeforeignfield.exit", // NOI18N
Boolean.valueOf(isPresent));
}
return isPresent;
| private void | recordUpdatedField(FieldDesc fieldDesc)Marks the field fieldDesc as set and schedules local fields
to be written to the data store.
boolean debug = logger.isLoggable(Logger.FINEST);
if (!fieldDesc.isRelationshipField() &&
(fieldDesc.sqlProperties & FieldDesc.PROP_RECORD_ON_UPDATE) > 0) {
if (debug) {
logger.finest("sqlstore.sqlstatemanager.recordingfield", fieldDesc); // NOI18N
}
getUpdateDesc().recordUpdatedField((LocalFieldDesc) fieldDesc);
}
if (debug) {
logger.finest("sqlstore.sqlstatemanager.makedirtyfield", fieldDesc); // NOI18N
}
setSetMaskBit(fieldDesc.absoluteID);
| public void | refreshPersistent()
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.refreshpersistent", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
// Only refresh if the state allows it.
if (state.isRefreshable()) {
LifeCycleState oldstate = state;
state = state.transitionRefreshPersistent();
reload(null);
registerInstance(false, null, oldstate);
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.refreshpersistent.exit"); // NOI18N
}
| private void | registerCreateDependency(ForeignFieldDesc inverseFieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM)The referred object has to be written to the store before the
relationship can be set. To ensure referentional integrity
constraints in the database, the added object has to be written
to the store, before the relationship can be set. The same
dependency applies for relationships mapped to a jointable.
if (!addedSM.state.isPersistentInDataStore()) {
addedSM.addUpdatedForeignReference(inverseFieldDesc, this);
}
| private void | registerInstance(boolean throwDuplicateException, java.util.ArrayList newlyRegisteredSMs, com.sun.jdo.spi.persistence.support.sqlstore.state.LifeCycleState oldstate)
if ((stateFlags & ST_REGISTERED) == 0 || // not registered or
(oldstate != state && // state changed from clean to dirty or transactional type.
(oldstate == null || oldstate.isDirty() != state.isDirty() ||
oldstate.isTransactional() != state.isTransactional()))) {
persistenceManager.registerInstance(this, getObjectId(), throwDuplicateException, false);
stateFlags |= ST_REGISTERED;
if (newlyRegisteredSMs != null) {
if (!newlyRegisteredSMs.contains(this))
newlyRegisteredSMs.add(this);
}
}
| private void | registerRemoveDependency(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM)Nullify the relationship in the data store before the _possible_ removal
of removedSM. To maintain referentional integrity constraints in the
database, the relationship to the removed instance has to be nullified,
before the removed object might be deleted. Since we use immediate
dependency management, we don't know, if the removed object is deleted
later on. The data store relationship has to be erased before the
removal. Immediate dependency management determines dependencies
immediatly when the relationship is set. In contrast the deferred
approach waits until the objects are flushed to the store. Set the
dependency only if both instances are already persistent.
if (this.state.isPersistentInDataStore() &&
removedSM.state.isPersistentInDataStore()) {
this.addUpdatedForeignReference(fieldDesc, removedSM);
}
| public void | release()
if (null != persistenceManager) {
// The persistenceManager can be null, for example if this
// instance is used in the VersionConsistency cache.
persistenceManager.setStateManager(persistentObject, null);
}
persistentObject = null;
objectId = null;
persistenceManager = null;
beforeImage = null;
hiddenValues = null;
updatedForeignReferences = null;
updateDesc = null;
persistenceConfig = null;
store = null;
valid = false;
| public void | releaseLock()Release lock.
lock.release();
| public void | reload()Reloads the instance by delegating actual work, state transition, and
instance registration to {@link #reload(FieldDesc) reload(FieldDesc)}
With null as an argument. Called by
{@link PersistenceManager#getObjectById(Object, boolean)
PersistenceManager.getObjectById(Object, boolean)} with validate
flag set to true
boolean debug = logger.isLoggable(Logger.FINER);
if (debug) {
logger.finer("sqlstore.sqlstatemanager.unconditionalreload", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
persistenceManager.acquireShareLock();
try {
getLock();
reload(null);
} finally {
persistenceManager.releaseShareLock();
releaseLock();
if (debug) {
logger.finer("sqlstore.sqlstatemanager.unconditionalreload.exit"); // NOI18N
}
}
| private void | reload(FieldDesc additionalField)Reloads this SM from the state in the datastore, getting data for the
given field.
boolean debug = logger.isLoggable();
if (debug) {
String fieldName =
(additionalField != null) ? additionalField.getName() : null;
logger.fine("sqlstore.sqlstatemanager.reload", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName(), fieldName);
}
// Clear the fields PresenceMask so all the currently present
// fields will be replaced.
clearMask(PRESENCE_MASK);
// Need to mark the key fields as present
markKeyFieldsPresent();
clearMask(SET_MASK);
LifeCycleState oldState = state;
state = state.transitionReload(persistenceManager.isActiveTransaction());
if (!retrieveFromVersionConsistencyCache(additionalField)) {
// Retrieve the instance from the data store, if this class
// is not version consistent, or not found in the cache.
try {
retrieve(additionalField);
} catch (JDOException e) {
// Reset the state if the instance couldn't be found.
state = oldState;
throw e;
}
}
registerInstance(false, null, oldState);
if (persistenceManager.getFlags(persistentObject) == LOAD_REQUIRED) {
persistenceManager.setFlags(persistentObject, READ_OK);
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.reload.exit"); // NOI18N
}
| private void | removeCollectionRelationship(ForeignFieldDesc fieldDesc, java.util.ArrayList removedList, ForeignFieldDesc inverseFieldDesc, boolean updateInverseRelationshipField, boolean managedRelationshipInProgress)Nullifies the relationship for the objects removed from a collection relationship.
for (int i = 0; i < removedList.size(); i++) {
SQLStateManager removedSM = getRemovedSM(removedList.get(i));
// removedSM == null can happen if the collection is non-SCO and contains
// transient instances which don't become persistent until commit.
if (removedSM != null) {
// The collection side never has the foreign key, i.e.
// it's never processed during relationship management,
// because data store updates are already done.
if (!managedRelationshipInProgress) {
updateRelationshipInDataStore(fieldDesc, null, removedSM, inverseFieldDesc, false);
// Relationship management
if (updateInverseRelationshipField && inverseFieldDesc != null) {
removedSM.removeRelationship(inverseFieldDesc, this);
}
}
}
}
| private void | removeDependency()Decrements the reference count and marks this instance
as updateable, if the reference count is zero.
if (--referenceCount == 0) {
stateFlags &= ~ST_UPDATE_DISABLED;
}
| private void | removeJoinTableEntry(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, ForeignFieldDesc inverseFieldDesc)Schedules the removal of the jointable entry between this and the
foreign state manager. A scheduled creation of the jointable entry
between these two objects is simply removed. The removal is
scheduled on the local side.
For dependency management, the removal of the jointable entry has
to precede the _possible_ removal of removedSM. The same dependency applies
to foreign key relationships, see {@link #registerRemoveDependency}.
RESOLVE: What happens, if a field descriptor is null, e.g. for one
way relationships, as the descriptors are taken as keys during scheduling?
// Cleanup dependencies. We need to cleanup dependencies for
// flushed autopersistent instances that aren't reachable
// before commit. See runtime test Autopersistence.TestCase12.
// The cleanup must be done for removals only, because the
// only operations executed in prepareToUpdatePhaseIII are
// removals.
if (removedSM.state.isAutoPersistent() || this.state.isAutoPersistent()) {
removedSM.removeUpdatedForeignReference(inverseFieldDesc, this);
this.removeUpdatedForeignReference(fieldDesc, removedSM);
}
// Remove scheduled creation on this side.
if (fieldDesc != null && getUpdateDesc().removeUpdatedJoinTableRelationship(
fieldDesc, removedSM, ActionDesc.LOG_CREATE) == false) {
// Remove scheduled creation on the other side.
if (inverseFieldDesc == null || removedSM.getUpdateDesc().removeUpdatedJoinTableRelationship(
inverseFieldDesc, this, ActionDesc.LOG_CREATE) == false) {
// Schedule removal on this side.
// The field descriptor taken as key must not be null, see above!
getUpdateDesc().recordUpdatedJoinTableRelationship(
fieldDesc, this, removedSM, ActionDesc.LOG_DESTROY);
// Remove the jointable entry before the _possible_ removal of removedSM.
registerRemoveDependency(fieldDesc, removedSM);
}
} else if (fieldDesc == null) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.cantschedulejointable", // NOI18N
this.getPersistenceConfig().getPersistenceCapableClass().getName(),
removedSM.getPersistenceConfig().getPersistenceCapableClass().getName()));
}
| private void | removeRelationship(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM)Updates the relationship field fieldDesc between this
and removedSM .
boolean isCollection = (fieldDesc.cardinalityUPB > 1);
if (!isCollection) {
prepareUpdateFieldSpecial(fieldDesc, removedSM.persistentObject, false);
updateTrackedFields(fieldDesc, null, null);
fieldDesc.setValue(this, null);
} else {
try {
prepareUpdateFieldSpecial(fieldDesc, null, true);
SCOCollection c = (SCOCollection) fieldDesc.getValue(this);
c.removeInternal(removedSM.persistentObject);
updateTrackedFields(fieldDesc, c, null);
} catch (ClassCastException e) {
// ignore
}
}
| private void | removeUpdatedForeignReference(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager sm)Removes the dependency from state manager sm on
this . State manager sm does not need to
wait for this to be flushed to the store. The dependency
was established to maintain referential integrity conditions in the
data store.
if ((updatedForeignReferences == null) ||
(updatedForeignReferences.size() == 0)) {
return;
}
if (updatedForeignReferences.remove(new UpdatedForeignReference(fieldDesc, sm))) {
sm.referenceCount--;
if (logger.isLoggable()) {
String fieldName = (fieldDesc != null) ? fieldDesc.getName() : null;
Object[] items = new Object[] {this.persistentObject, fieldName,
sm.persistentObject, new Integer(sm.referenceCount)};
logger.fine("sqlstore.sqlstatemanager.removeupdate", items); // NOI18N
}
if (sm.referenceCount == 0) {
sm.stateFlags &= ~ST_UPDATE_DISABLED;
}
}
| public synchronized void | replaceCollection(ForeignFieldDesc ff, java.util.Collection c)This method serves two purposes:
1. If the field value is null or contains a non-SCOCollection instance, it
creates a new SCOCollection and populates with elements in c.
2. If the field value is a SCOCollection instance, then if it is deferred,
it calls applyDeferredUpdates on the collection passing in c. Otherwise,
it clears the collection and repopulates with elements in c.
Collection collection = (Collection) ff.getValue(this);
SCOCollection scoCollection = null;
if ((collection == null) || !(collection instanceof SCO)) {
scoCollection = (SCOCollection) persistenceManager.newCollectionInstanceInternal(
ff.getType(), persistentObject, ff.getName(),
ff.getComponentType(), false, ((c != null) ? c.size() : 0));
ff.setValue(this, scoCollection);
scoCollection.addAllInternal(c);
} else {
scoCollection = (SCOCollection) collection;
if (scoCollection.isDeferred()) {
scoCollection.applyDeferredUpdates(c);
// We need to mark all the tracked fields as present.
ArrayList trackedFields = ff.getTrackedFields();
if (trackedFields != null) {
for (int i = 0; i < trackedFields.size(); i++) {
ForeignFieldDesc tf = (ForeignFieldDesc) trackedFields.get(i);
setPresenceMaskBit(tf.absoluteID);
}
}
} else {
scoCollection.clearInternal();
scoCollection.addAllInternal(c);
}
}
// Should not use old collection as SCO if any
if (c != null && c instanceof SCO) {
((SCO) c).unsetOwner();
}
| public synchronized void | replaceObjectField(java.lang.String fieldName, java.lang.Object o)
boolean debug = logger.isLoggable();
if (debug) {
Object[] items = new Object[] {fieldName, o.getClass().getName()};
logger.fine("sqlstore.sqlstatemanager.replaceobjectfield", items); // NOI18N
}
FieldDesc fieldDesc = persistenceConfig.getField(fieldName);
Object oldo = prepareSetField(fieldDesc, o);
if ((oldo instanceof SCO) && oldo != o) {
if (debug)
logger.fine("sqlstore.sqlstatemanager.replaceobjectfield.unsetsco"); // NOI18N
((SCO) oldo).unsetOwner();
}
| private boolean | requiresImmediateFlush(com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager next)This method checks whether this StateManager instance needs to be
flushed immediately during beforeCompletion. A return of false
means the store manager is allowed to combine flushing of these two
instance in a single database roundtrip (e.g. by using batched updates).
// There is no next SM =>
// flush this sm immediately
if (next == null)
return true;
// The next StateManager has a different pc class =>
// flush this sm immediately
if (persistenceConfig != next.persistenceConfig)
return true;
// The next StateManager represents a different update operation
// INSERT/UPDATE/DELETE => flush this sm immediately
if (state.getUpdateAction() != next.state.getUpdateAction())
return true;
// If the next's flush is disabled, flush this sm
if ((next.stateFlags & ST_UPDATE_DISABLED) > 0)
return true;
// If next sm does not use batch update flush this sm
if (!next.useBatch())
return true;
// For updates, we need to check if the next sm updates the
// same fields. If not, flush this sm
if (getUpdateDesc().getUpdateAction() == ActionDesc.LOG_UPDATE &&
!compareUpdatedFields(next)) {
return true;
}
// If the next stateManager has got (foreign reference) dependencies,
// it is not considered for batching at all
if (next.updatedForeignReferences != null) {
return true;
}
// Now we can make use of batching w/o flushing
return false;
| private void | reset(boolean retainValues, boolean wasNew, boolean keepState)
boolean debug = logger.isLoggable();
if (debug) {
Object[] items = new Object[] {Boolean.valueOf(retainValues),
Boolean.valueOf(wasNew), Boolean.valueOf(keepState)};
logger.fine("sqlstore.sqlstatemanager.reset", items); // NOI18N
}
if (state == null) {
// make the instance transient.
if (!keepState) {
persistenceManager.clearFields(persistentObject);
}
// Need to set jdoFlag to READ_WRITE_OK for transient instance.
persistenceManager.setFlags(persistentObject, READ_WRITE_OK);
if (needsVerifyAtDeregister) {
persistenceManager.deregisterInstance(getObjectId(), this);
} else {
persistenceManager.deregisterInstance(getObjectId());
}
this.release();
} else {
// Reset the state manager for the next transaction.
stateFlags = 0;
beforeImage = null;
updatedForeignReferences = null;
referenceCount = 0;
if (updateDesc != null) {
updateDesc.reset();
}
// We retain the field values if retainValues is true or the state
// is persistentNontransactional
if (retainValues || (state instanceof PersistentNonTransactional)) {
FieldDesc f = null;
ArrayList fields = persistenceConfig.fields;
for (int i = 0; i < fields.size(); i++) {
f = (FieldDesc) fields.get(i);
Object v = f.getValue(this);
// For new objects mark null references as not set if the field is
// not managed. This is to allow the field to be reloaded in the next
// transaction because a relationship may exist in the database.
if (wasNew && (f instanceof ForeignFieldDesc) &&
(v == null) && (((ForeignFieldDesc) f).getInverseRelationshipField() == null)) {
if (debug)
logger.fine("sqlstore.sqlstatemanager.unsetmask", f.getName()); // NOI18N
unsetMaskBit(f.absoluteID, PRESENCE_MASK);
}
// Replace java.util Collection and Date objects
// with SCO instances:
if ((v instanceof Collection) && !(v instanceof SCOCollection)
&& !keepState) {
if (debug)
logger.fine("sqlstore.sqlstatemanager.resettingcollection"); // NOI18N
replaceCollection((ForeignFieldDesc) f, (Collection) v);
if (debug) {
logger.fine("sqlstore.sqlstatemanager.newtype", (f.getValue(this)).getClass()); // NOI18N
}
} else if (v instanceof SCOCollection) {
((SCOCollection) v).reset();
}
// TO FIX!!!: this already replaces Date with SCO Date
else if ((v instanceof java.util.Date) && !(v instanceof SCODate)
&& !keepState) {
if (debug)
logger.fine("sqlstore.sqlstatemanager.resettingdate"); // NOI18N
v = f.convertValue(v, this);
f.setValue(this, v);
if (debug) {
logger.fine("sqlstore.sqlstatemanager.newtype", (f.getValue(this)).getClass()); // NOI18N
}
}
}
// We need to set the jdoFlags to LOAD_REQUIRED instead of READ_OK in order to
// have the StateManager intermediate access to this instance. The reason is
// if the next transaction is pessimistic, the StateManager needs to reload
// the instance. Note that the StateManager will not reload the instance
// if the transaction is optimistic and the instance is p_nontransactional.
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
} else {
clearMask(PRESENCE_MASK);
persistenceManager.clearFields(persistentObject);
// Need to mark the key fields as present
markKeyFieldsPresent();
persistenceManager.setFlags(persistentObject, LOAD_REQUIRED);
}
clearMask(SET_MASK);
isReplacementInstance = false;
needsRegisterAtRollback = false;
needsVerifyAtDeregister = false;
}
| public void | resolveDependencies()Resolves the dependencies for the instances waiting for this state manager.
Dependencies are registered instantly during the course of the transaction.
For this reason, the introduced dependencies must be checked, if they are
still valid at commit/flush. E.g. remove dependencies introduced on
relationship removal are only valid, if the removed instance is deleted.
This method checks the dependencies for all instances waiting for the
current state manager to be flushed to the store.
if (logger.isLoggable()) {
logger.fine("sqlstore.sqlstatemanager.resolvedependencies", this.getPersistent()); // NOI18N
}
if (updatedForeignReferences != null) {
Iterator iter = updatedForeignReferences.iterator();
while (iter.hasNext()) {
final UpdatedForeignReference ufr = (UpdatedForeignReference) iter.next();
final ForeignFieldDesc fieldDesc = ufr.getFieldDesc();
final SQLStateManager foreignSM = ufr.getStateManager();
if (resolveDependency(fieldDesc, foreignSM)) {
foreignSM.removeDependency();
iter.remove();
}
}
}
| private boolean | resolveDependency(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager foreignSM)Tries to resolve the dependency between this
and foreignSM introduced on the update of
relationship field fieldDesc . There are three
kinds of dependencies:
- Create dependency, see {@link #registerRemoveDependency}
- Remove dependency, see {@link #registerCreateDependency}
- Update dependency, see {@link #manageDependencyForObjectField}
The current implementation does not attempt to resolve
Update dependencies.
boolean removeDependency = false;
Object pc = foreignSM.getPersistent();
if (!state.isPersistentInDataStore()) {
// Check for a create dependency.
// The create dependency is valid, if the instance is being created.
if (state.getUpdateAction() != ActionDesc.LOG_CREATE) {
// The instance is not persistent and will not be created.
removeDependency = true;
} else if (!checkRelationship(this, fieldDesc, pc)) {
// No relationship between the two instances.
removeDependency = true;
}
} else {
// Not removable dependencies are marked by fieldDesc == null.
// See delete/create with the same id dependency in addDependency
// or update dependencies in manageDependencyForObjectField.
// RESOLVE: Are update dependencies removable?
if (fieldDesc != null) {
// Check for a remove dependency.
// The remove dependency is valid, if the formerly referred
// instance is being removed.
if (foreignSM.state.getUpdateAction() != ActionDesc.LOG_DESTROY) {
// The formerly referred instance will not be removed.
removeDependency = true;
} else if (fieldDesc.cardinalityUPB <= 1) {
// Don't check collection relationships, as collection
// fields might not be populated in the before image.
// RESOLVE: Collection relationships shouldn't be
// checked for remove dependencies anyway.
if (!checkRelationship(beforeImage, fieldDesc, pc)) {
// No previous relationship between the two instances.
removeDependency = true;
}
}
}
}
if (removeDependency && logger.isLoggable()) {
Object[] items = new Object[] {this.getPersistent(), fieldDesc.getName(), pc};
logger.fine("sqlstore.sqlstatemanager.resolvedependency", items); // NOI18N
}
return removeDependency;
| private void | retrieve(FieldDesc additionalField)The retrieve method gets a retrieve descriptor to retrieve the
desired field and adds constraints necessary to limit the
retrieval set to the source object runs the retrieve
descriptor against the store, the source object is connected to,
and then merges the results back into the source object.
boolean debug = logger.isLoggable();
if (debug) {
String fieldName = (additionalField != null) ? additionalField.getName() : null;
logger.fine("sqlstore.sqlstatemanager.retrieve", fieldName); // NOI18N
}
LocalFieldDesc[] keyFields = persistenceConfig.getKeyFieldDescs();
Object [] values = new Object[keyFields.length];
copyValues(values, keyFields, 0);
// Getting a new generated RD or a cached one.
RetrieveDesc rd = persistenceConfig.getRetrieveDescForPKQuery(additionalField, store);
Collection result = (Collection) store.
retrieve(persistenceManager, rd, new QueryValueFetcher(values));
if (result.size() > 1) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.toomanyrows", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName()));
} else if (result.size() < 1 || result.iterator().next() != persistentObject) {
// If there are no instances fetched, or the fetched instances is not the one
// we asked for, it means that it is not found and we throw an exception
throw new JDOObjectNotFoundException(I18NHelper.getMessage(messages,
"core.statemanager.objectnotfound"), // NOI18N
new Object[]{persistentObject});
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.retrieve.exit"); // NOI18N
}
| private java.util.Collection | retrieveForeign(ForeignFieldDesc foreignField)Retrieves the relationship based on the values of the
relationship columns on the local side. Note: This method
assumes that the relationship key fields are loaded.
RESOLVE:
The relationship might be mapped to an Unique Key.
Do databases constrain the Unique Key columns to be non null?
assert foreignField != null;
Collection result = null;
boolean debug = logger.isLoggable();
if (debug) {
logger.fine("sqlstore.sqlstatemanager.retrieveforeign", // NOI18N
foreignField.getName());
}
Object[] values = new Object[foreignField.localFields.size()];
boolean isValidForeignKey = true;
for (int i = 0; i < foreignField.localFields.size(); i++) {
FieldDesc flf = (FieldDesc) foreignField.localFields.get(i);
if (!getPresenceMaskBit(i)) {
// throw exception
}
if (getSetMaskBit(flf.absoluteID)) {
// This is one reason why we must have a before image
// on relationship changes!
values[i] = flf.getValue(beforeImage);
} else {
values[i] = flf.getValue(this);
}
// Make sure we have a valid query key.
if (values[i] == null) {
// The relationship must be null. No need to query!
isValidForeignKey = false;
}
}
if (isValidForeignKey) {
// Getting a new generated RD or a cached one.
RetrieveDesc fdesc =
persistenceConfig.getRetrieveDescForFKQuery(foreignField, store);
result = (Collection) store.retrieve(
persistenceManager, fdesc, new QueryValueFetcher(values));
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.retrieveforeign.exit"); // NOI18N
}
return result;
| private boolean | retrieveFromVersionConsistencyCache(FieldDesc additionalField)Initialize this SM from the version consistency cache. If this
SM is in the cache and the additional field is not populated,
the field is retrieved from the store.
boolean rc =
persistenceManager.initializeFromVersionConsistencyCache(this);
if (rc) {
// make sure additionalField is available
if (additionalField != null
&& !getPresenceMaskBit(additionalField.absoluteID)) {
realizeField(additionalField);
}
}
return rc;
| public void | rollback(boolean retainValues)
boolean wasNew = (state.isNew() && !state.isDeleted());
boolean needsRestore = state.needsRestoreOnRollback(retainValues);
state = state.transitionRollback(retainValues);
boolean keepState = needsRestore;
// Only restore if there is a before image and the flag needsRestore is true.
if ((beforeImage != null) && (needsRestore == true)) {
copyFields(beforeImage, true, false);
// Keep the fields from being reset in reset()
keepState = true;
}
if (needsRegisterAtRollback && !isReplacementInstance) {
persistenceManager.registerInstance(this, getObjectId());
}
reset(retainValues, wasNew, keepState);
| public boolean[] | setBooleanArrayField(int fieldNumber, boolean[] value)
prepareSetField(fieldNumber, null);
return value;
| public boolean | setBooleanField(int fieldNumber, boolean value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Boolean(value));
return value;
| public byte[] | setByteArrayField(int fieldNumber, byte[] value)
prepareSetField(fieldNumber, null);
return value;
| public byte | setByteField(int fieldNumber, byte value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Byte(value));
return value;
| public char | setCharArrayField(int fieldNumber, char value)
prepareSetField(fieldNumber, null);
return value;
| public char | setCharField(int fieldNumber, char value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Character(value));
return value;
| public double[] | setDoubleArrayField(int fieldNumber, double[] value)
prepareSetField(fieldNumber, null);
return value;
| public double | setDoubleField(int fieldNumber, double value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Double(value));
return value;
| public byte | setFlags(byte flags)...
// RESOLVE: Need to verify that the flags are valid with the current
// state of the state manager.
return flags;
| public float[] | setFloatArrayField(int fieldNumber, float[] value)
prepareSetField(fieldNumber, null);
return value;
| public float | setFloatField(int fieldNumber, float value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Float(value));
return value;
| private void | setForeignKey(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, ForeignFieldDesc inverseFieldDesc)Sets the foreign key corresponding to the relationship field
fieldDesc . Usually the foreign key columns are not mapped
explicitly by the user. For this reason the runtime creates hidden fields
representing the foreign key columns internally. We determine the local
fields by iterating appropriate field list of either
fieldDesc or inverseFieldDesc .
To ensure referentional integrity constraints in the database,
the added object has to be written to the store, before the
foreign key can be set. The same dependency applies to relationships
mapped to jointables, see {@link #addJoinTableEntry}.
if (!isDeleted()) {
// fieldDesc can be null for one-directional relationships. We are
// only interested in the LocalFieldDescs for the foreign key columns,
// which can also be retrieved from inverseFieldDesc.
if (fieldDesc != null) {
for (int i = 0; i < fieldDesc.localFields.size(); i++) {
LocalFieldDesc la = (LocalFieldDesc) fieldDesc.localFields.get(i);
LocalFieldDesc fa = (LocalFieldDesc) fieldDesc.foreignFields.get(i);
setForeignKey(fieldDesc, la, fa.getValue(addedSM));
}
} else {
for (int i = 0; i < inverseFieldDesc.foreignFields.size(); i++) {
LocalFieldDesc la = (LocalFieldDesc) inverseFieldDesc.foreignFields.get(i);
LocalFieldDesc fa = (LocalFieldDesc) inverseFieldDesc.localFields.get(i);
setForeignKey(fieldDesc, la, fa.getValue(addedSM));
}
}
}
// The referred object has to be written to the store before the foreign key can be set.
registerCreateDependency(inverseFieldDesc, addedSM);
| private void | setForeignKey(ForeignFieldDesc fieldDesc, LocalFieldDesc la, java.lang.Object faValue)Actually sets the local field la corresponding to a foreign
key column to the new value for the relationship update. The new value
is taken from fa , which is typically a primary key field on
the other relationship side. Fields tracking the foreign key field
la are updated.
if (!getSetMaskBit(la.absoluteID)) {
prepareUpdateField(la, null);
}
if (la.isKeyField()) {
assertPKUpdate(la, faValue);
}
updateTrackedFields(la, faValue, fieldDesc);
la.setValue(this, faValue);
| public void | setHiddenValue(int index, java.lang.Object value)
// This method expects index to be negative for hidden fields.
if (index >= 0) {
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.statemanager.poshiddenindex", "" + index)); // NOI18N
}
int realIndex = -(index + 1);
if (hiddenValues == null) {
hiddenValues = new ArrayList();
}
for (int i = hiddenValues.size(); i <= realIndex; i++) {
hiddenValues.add(null);
}
hiddenValues.set(realIndex, value);
| public int[] | setIntArrayField(int fieldNumber, int[] value)
prepareSetField(fieldNumber, null);
return value;
| public int | setIntField(int fieldNumber, int value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Integer(value));
return value;
| public long[] | setLongArrayField(int fieldNumber, long[] value)
prepareSetField(fieldNumber, null);
return value;
| public long | setLongField(int fieldNumber, long value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Long(value));
return value;
| public java.lang.Object[] | setObjectArrayField(int fieldNumber, java.lang.Object[] value)
prepareSetField(fieldNumber, value);
return value;
| public java.lang.Object | setObjectField(int fieldNumber, java.lang.Object value)This method sets object fields, e.g. relationship fields.
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, value);
return value;
| public void | setObjectId(java.lang.Object objectId)
// RESOLVE: do we allow to replace existing?
this.objectId = objectId;
| public void | setPersistenceManager(com.sun.jdo.api.persistence.support.PersistenceManager pm)
this.persistenceManager = (PersistenceManager) pm;
| public void | setPersistent(java.lang.Object pc)
this.persistentObject = pc;
| public void | setPresenceMaskBit(int index)
if (fieldMasks == null) {
newFieldMasks();
}
if (index >= 0) {
fieldMasks.set(index + PRESENCE_MASK * persistenceConfig.maxFields);
} else {
fieldMasks.set(-(index + 1) + persistenceConfig.maxVisibleFields +
PRESENCE_MASK * persistenceConfig.maxFields);
}
| private void | setSetMaskBit(int index)
if (fieldMasks == null) {
newFieldMasks();
}
if (index >= 0) {
fieldMasks.set(index + SET_MASK * persistenceConfig.maxFields);
} else {
fieldMasks.set(-(index + 1) + persistenceConfig.maxVisibleFields +
SET_MASK * persistenceConfig.maxFields);
}
| public short[] | setShortArrayField(int fieldNumber, short[] value)
prepareSetField(fieldNumber, null);
return value;
| public short | setShortField(int fieldNumber, short value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, new Short(value));
return value;
| public java.lang.String[] | setStringArrayField(int fieldNumber, java.lang.String[] value)
prepareSetField(fieldNumber, null);
return value;
| public java.lang.String | setStringField(int fieldNumber, java.lang.String value)
assertNotPK(fieldNumber);
prepareSetField(fieldNumber, value);
return value;
| public void | setValid()Mark this StateManager as valid. Called before returning from
getObjectById.
try {
getLock();
valid = true;
} finally {
releaseLock();
}
| public void | setVerificationFailed()
if (hasVersionConsistency()) {
stateFlags |= ST_VALIDATION_FAILED;
}
| private void | setVisibleMaskBits(int mask)
if (fieldMasks == null) {
newFieldMasks();
}
int offset = mask * persistenceConfig.maxFields;
fieldMasks.set(offset, offset + persistenceConfig.maxVisibleFields);
| public boolean | testIsAutoPersistent()
return state.isAutoPersistent();
| public boolean | testIsLoaded(int fieldNumber)
return getPresenceMaskBit(fieldNumber);
| public boolean | testIsLoaded(java.lang.String fieldName)
FieldDesc f = persistenceConfig.getField(fieldName);
return testIsLoaded(f.absoluteID);
| private void | transitionPersistent(java.lang.Object pc, java.util.HashSet phase3sms)Transitions the instance pc to persistent state if it's
autopersistent, and removes its state manager from the list
phase3sms of unreachable autopersistent
instances. The recursive call to prepareToUpdatePhaseII
removes the transitive closure of all state managers reachable from
pc from phase3sms . This method has got no
effects on transient instances.
SQLStateManager sm = (SQLStateManager) persistenceManager.getStateManager(pc);
// Need to check if the associated state manager is null, if
// called with an object from a collection relationship field. If
// the collection is not a SCO collection, it is possible that it
// contains transient instances. No need to check for object
// relationship fields.
if (sm != null && sm.state.isAutoPersistent()) {
sm.state = sm.state.transitionMakePersistent();
phase3sms.remove(sm);
sm.prepareToUpdatePhaseII(phase3sms);
}
| private void | unsetMaskBit(int index, int mask)
if (fieldMasks == null) {
newFieldMasks();
} else {
if (index >= 0) {
fieldMasks.clear(index + mask * persistenceConfig.maxFields);
} else {
fieldMasks.clear(-(index + 1) + persistenceConfig.maxVisibleFields +
mask * persistenceConfig.maxFields);
}
}
| private void | updateBeforeImage(FieldDesc fieldDesc, java.lang.Object value)Initializes the beforeImage and registers the before image
value if not null.
getBeforeImage();
if (beforeImage != null
&& !beforeImage.getPresenceMaskBit(fieldDesc.absoluteID)
&& (fieldDesc.sqlProperties & FieldDesc.PROP_LOG_ON_UPDATE) > 0) {
if (value == null) {
value = fieldDesc.getValue(this);
}
if (value != null) {
if (logger.isLoggable(Logger.FINEST)) {
Object[] items = new Object[] {fieldDesc, value};
logger.finest("sqlstore.sqlstatemanager.updatebeforeimage", items); // NOI18N
}
fieldDesc.setValue(beforeImage, cloneObjectMaybe(value));
beforeImage.setPresenceMaskBit(fieldDesc.absoluteID);
}
}
| private void | updateCollectionField(ForeignFieldDesc fieldDesc, java.util.Collection value, boolean managedRelationshipInProgress)Sets the new value for the collection field by calling
{@link #processCollectionUpdates}.
boolean debug = logger.isLoggable(Logger.FINEST);
if (debug) {
Object[] items = new Object[] {value,((value == null)? "NO" : value.getClass().getName())}; // NOI18N
logger.finest("sqlstore.sqlstatemanager.processforeignfield", items); // NOI18N
}
Object currVal = fieldDesc.getValue(this);
// Do nothing if the current value is identical to the new value.
if (currVal != value) {
Object owner = null;
ArrayList added = null;
ArrayList removed = null;
// Verify SCO owner and fieldName if any
if (value != null && value instanceof SCOCollection) {
SCOCollection sco = (SCOCollection) value;
owner = sco.getOwner();
if (owner == null) {
sco.setOwner(persistentObject, fieldDesc.getName(),
fieldDesc.getComponentType());
} else if (owner != persistentObject ||
!fieldDesc.getName().equals(sco.getFieldName())) {
throw new JDOUserException(I18NHelper.getMessage(
messages, "core.statemanager.anotherowner"), // NOI18N
new Object[]{owner, sco.getFieldName()});
}
// SCO should not behave as a JDK collection,
// but become owned and tracked at setXXX operation.
added = new ArrayList(value);
}
Object befrVal = fieldDesc.getValue(beforeImage);
if (currVal != null) {
if (debug)
logger.finest("sqlstore.sqlstatemanager.processforeignfield.remove"); // NOI18N
// This is a setXXX (i.e. replace) operation, we need to
// "remove" elements from the current SCOCollection and mark it as not used
if (((Collection) currVal).size() > 0) {
removed = new ArrayList((Collection) currVal);
}
if (currVal instanceof SCOCollection) {
if (debug)
logger.finest("sqlstore.sqlstatemanager.processforeignfield.reset"); // NOI18N
// SCOCollection: mark it as not used
((SCO) currVal).unsetOwner();
}
} else if (getSetMaskBit(fieldDesc.absoluteID) == false && befrVal != null)
// && value instanceof SCOCollection && owner != null)
{
if (debug)
logger.finest("sqlstore.sqlstatemanager.processforeignfield.remove_from_bi"); // NOI18N
// Replace with SCOCollection: mark beforeImage as removed
if (((Collection) befrVal).size() > 0) {
removed = new ArrayList((Collection) befrVal);
}
}
processCollectionUpdates(fieldDesc, removed, added, null, true,
managedRelationshipInProgress);
}
| private boolean | updateObjectField(ForeignFieldDesc fieldDesc, java.lang.Object addedObject, boolean updateInverseRelationshipField, boolean managedRelationshipInProgress)Handles relationship updates for the object side of a one-to-many or both
sides of a one-to-one relationship. This method processes i.e. the
Employee side of the Employee-Department, or both sides
Employee-Insurance relationship. Nullifies the relation on the instance
removed from the relationship. The relation is set on the added instance
value . Data store updates are scheduled. Updates the inverse
relationship side if updateInverseRelationshipField == true
and the relationship is mapped as bi-directional by the user.
boolean debug = logger.isLoggable();
if (debug) {
Object[] items = new Object[] {fieldDesc.getName(),fieldDesc.getComponentType()};
logger.fine("sqlstore.sqlstatemanager.updateobjfield", items); // NOI18N
}
Object removedObject = fieldDesc.getValue(this);
// Don't do anything if the before and after value are the same.
if (addedObject != removedObject) {
SQLStateManager addedSM = getAddedSM(addedObject, null);
SQLStateManager removedSM = getRemovedSM(removedObject);
SQLStateManager addedInverseFieldSM = null;
// If the new value is already deleted, we throw an exception.
if (addedSM != null && addedSM.isDeleted()) {
JDOUserException ex = new JDOUserException(I18NHelper.getMessage(messages,
"jdo.lifecycle.deleted.accessField")); // NOI18N
ex.addFailedObject(addedObject);
throw ex;
}
ForeignFieldDesc inverseFieldDesc = fieldDesc.getInverseRelationshipField();
updateRelationshipInDataStore(fieldDesc, addedSM, removedSM,
inverseFieldDesc, managedRelationshipInProgress);
if (updateInverseRelationshipField && inverseFieldDesc != null) {
addedInverseFieldSM = manageRelationshipForObjectField(inverseFieldDesc, addedSM, removedSM,
managedRelationshipInProgress);
}
manageDependencyForObjectField(fieldDesc, addedSM, removedSM, addedInverseFieldSM);
}
if (debug) {
logger.fine("sqlstore.sqlstatemanager.updateobjfield.exit"); // NOI18N
}
return true;
| public void | updatePersistent(StateManager next)Stores the associated object in the datastore. This method is
called by {@link PersistenceManager#beforeCompletion} on
flush/commit. The specified state manager argument is used to
determine whether the actual instance should be flushed
immediately or whether batch update is possible.
boolean debug = logger.isLoggable();
if ((stateFlags & ST_UPDATE_DISABLED) > 0) {
if (debug) {
Object[] items = new Object[] {persistenceConfig.getPersistenceCapableClass().getName(),
persistentObject};
logger.fine("sqlstore.sqlstatemanager.updatepersistent.skipped", items); // NOI18N
}
return;
}
try {
if (debug) {
logger.fine("sqlstore.sqlstatemanager.updatepersistent", // NOI18N
persistenceConfig.getPersistenceCapableClass().getName());
}
ArrayList actions = new ArrayList();
// Get a list of actions to perform.
getUpdateActions(actions);
if (actions.size() == 1 && useBatch()) {
// Batch update only if actions consists of a single action
UpdateObjectDesc updateDesc = (UpdateObjectDesc)actions.get(0);
boolean immediateFlush = requiresImmediateFlush((SQLStateManager)next);
if (debug && immediateFlush) {
Object[] items = new Object[] {getPersistent(), (next != null) ? next.getPersistent() : null};
logger.fine("sqlstore.sqlstatemanager.updatepersistent.immediateflush", items); // NOI18N
}
store.executeBatch(persistenceManager, updateDesc, immediateFlush);
} else if (actions.size() > 0) {
store.execute(persistenceManager, actions);
}
incrementVersion(actions);
if (debug) {
logger.fine("sqlstore.sqlstatemanager.updatepersistent.exit"); // NOI18N
}
} catch (JDOException e) {
e.addFailedObject(persistentObject);
throw e;
} catch (Exception e) {
logger.throwing("sqlstore.SQLStateManager", "updatePersistent", e); // NOI18N
throw new JDOFatalInternalException(I18NHelper.getMessage(messages,
"core.generic.unknownexception"), e); // NOI18N
}
| private void | updateRelationshipInDataStore(ForeignFieldDesc fieldDesc, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager addedSM, com.sun.jdo.spi.persistence.support.sqlstore.SQLStateManager removedSM, ForeignFieldDesc inverseFieldDesc, boolean managedRelationshipInProgress)Updates the relationship in the data store. Updates the (hidden) local fields
corresponding to the foreign key columns if the relationship is mapped to a
foreign key. Jointable entries are scheduled for creation/removal if the
relationship is mapped to a jointable.
if (!fieldDesc.useJoinTable()) {
processForeignKeys(fieldDesc, addedSM, removedSM, inverseFieldDesc,
managedRelationshipInProgress);
} else {
processJoinTableEntries(fieldDesc, addedSM, removedSM, inverseFieldDesc,
managedRelationshipInProgress);
}
| private void | updateTrackedFields(FieldDesc fieldDesc, java.lang.Object value, ForeignFieldDesc fieldToIgnore)Updates the values for fields tracking field
fieldDesc . Must be called before the new value
for field fieldDesc is actually set.
If called when setting the local fields mapped to the
relationship on relationship updates, the relationship field
tracked by fieldDesc must be ignored when
propagating the changes.
For overlapping pk/fk situations or if a fk column is
explicitly mapped to a visible field, the update of the local
field triggers the update of the relationship field tracking
the local field.
ArrayList trackedFields = fieldDesc.getTrackedFields();
if (trackedFields == null) {
return;
}
boolean debug = logger.isLoggable(Logger.FINEST);
if (debug) {
Object[] items = new Object[] {fieldDesc.getName(), value,
((fieldToIgnore != null) ? fieldToIgnore.getName() : null)};
logger.finest("sqlstore.sqlstatemanager.updatetrackedfields", items); // NOI18N
}
Object currentValue = fieldDesc.getValue(this);
int size = trackedFields.size();
ArrayList fieldsToIgnore = ((fieldToIgnore != null) ? fieldToIgnore.getTrackedFields() : null);
if (fieldDesc instanceof ForeignFieldDesc) {
// For tracked relationship fields, we simply set the new value.
for (int i = 0; i < size; i++) {
ForeignFieldDesc tf = (ForeignFieldDesc) trackedFields.get(i);
prepareUpdateFieldSpecial(tf, currentValue, false);
tf.setValue(this, value);
}
} else {
Object previousValues[] = new Object[size];
LocalFieldDesc primaryTrackedField = null;
Object primaryTrackedFieldValue = null;
if ((fieldDesc.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) > 0) {
primaryTrackedField = (LocalFieldDesc) fieldDesc;
primaryTrackedFieldValue = value;
}
for (int i = 0; i < size; i++) {
FieldDesc tf = (FieldDesc) trackedFields.get(i);
if (tf instanceof LocalFieldDesc) {
Object convertedValue = null;
Object convertedCurrentValue = null;
// RESOLVE: SCODate is problematic because convertValue unsets
// the owner. The SCO to be used for restoring is broken.
try {
convertedValue = tf.convertValue(value, this);
convertedCurrentValue = tf.convertValue(currentValue, this);
} catch (JDOUserException e) {
// We got a conversion error. We need to revert all
// the tracked fields to their previous values.
// NOTE: We don't have to revert relationship fields
// because they come after all the primitive fields.
for (int j = 0; j < i; j++) {
tf = (FieldDesc) trackedFields.get(j);
tf.setValue(this, previousValues[j]);
}
throw e;
}
if ((tf.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) > 0) {
primaryTrackedField = (LocalFieldDesc) tf;
primaryTrackedFieldValue = convertedValue;
}
prepareUpdateFieldSpecial(tf, convertedCurrentValue, false);
// save the previous values for rollback
previousValues[i] = tf.getValue(this);
tf.setValue(this, convertedValue);
} else {
// We bypass fieldToIgnore and its trackedFields
if (((stateFlags & ST_FIELD_TRACKING_INPROGRESS) > 0)
|| (tf == fieldToIgnore)
|| ((fieldsToIgnore != null) && fieldsToIgnore.contains(tf))) {
continue;
}
ForeignFieldDesc ftf = (ForeignFieldDesc) tf;
Object pc = null;
if (primaryTrackedFieldValue != null) {
pc = getObjectById(ftf, primaryTrackedField, primaryTrackedFieldValue, false);
}
stateFlags |= ST_FIELD_TRACKING_INPROGRESS;
prepareSetField(ftf, pc);
stateFlags &= ~ST_FIELD_TRACKING_INPROGRESS;
}
}
}
if (debug) {
logger.finest("sqlstore.sqlstatemanager.updatetrackedfields.exit"); // NOI18N
}
| private boolean | useBatch()Returns true if batch update might be used to store the changes
of this state manager.
TODO: Because batched statements on Oracle don't return a
valid success indicator, batching is disabled for Version
Consistency.
boolean result = false;
if (USE_BATCH) {
switch(state.getUpdateAction()) {
case ActionDesc.LOG_CREATE:
result = !getUpdateDesc().hasChangedRelationships() &&
!getUpdateDesc().hasModifiedLobField();
break;
case ActionDesc.LOG_DESTROY:
case ActionDesc.LOG_UPDATE:
// Do not try to batch in optimitic tx for now. We need to
// check for parallel updates, so the WHERE clause checks
// the values from the beforeImage. We need a different SQL
// statements for the null vs. non null case.
result = !persistenceManager.isOptimisticTransaction() &&
!persistenceConfig.hasModifiedCheckAtCommitConsistency() &&
!getUpdateDesc().hasChangedRelationships() &&
!getUpdateDesc().hasModifiedLobField() &&
!hasVersionConsistency();
break;
default:
result = false;
break;
}
}
return result;
| public boolean | verifyPersistent()
assert persistenceConfig.hasVersionConsistency();
boolean verified = true;
if (state instanceof PersistentClean) {
RetrieveDesc verificationRD = persistenceConfig.getRetrieveDescForVerificationQuery(store);
LocalFieldDesc[] keyFields = persistenceConfig.getKeyFieldDescs();
LocalFieldDesc[] versionFields = persistenceConfig.getVersionFields();
// Please make sure that the order of parameter values is same as
// order of parameters as defined by ClassDesc#getRetrieveDescForVerificationQuery()
Object [] parameters = new Object[keyFields.length + versionFields.length];
copyValues(parameters, keyFields, 0);
copyValues(parameters, versionFields, keyFields.length);
// verificationRD requires parameters for pk field and version fields
Boolean result = (Boolean) store.
retrieve(persistenceManager, verificationRD, new QueryValueFetcher(parameters));
verified = result.booleanValue();
}
return verified;
|
|