Search in sources :

Example 1 with SCO

use of org.datanucleus.store.types.SCO in project datanucleus-rdbms by datanucleus.

the class JoinSetStore method elementAlreadyContainsOwnerInMtoN.

/**
 * Convenience method to check if an element already refers to the owner in an M-N relation (i.e added from other side).
 * @param ownerOP ObjectProvider of the owner
 * @param element The element
 * @return Whether the element contains the owner
 */
private boolean elementAlreadyContainsOwnerInMtoN(ObjectProvider ownerOP, Object element) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    if (ec.getOperationQueue() != null) {
        // TODO This means we always do a "SELECT 1 FROM JOINTABLE" for every addition when optimistic. Should seek to avoid this by updates to operationQueue maybe
        if (locate(ownerOP, element)) {
            NucleusLogger.DATASTORE.info(Localiser.msg("056040", ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerOP.getObject()), element));
            return true;
        }
        return false;
    }
    ObjectProvider elementOP = ec.findObjectProvider(element);
    if (elementOP != null) {
        // Check the collection at the other side whether already added (to avoid the locate call)
        AbstractMemberMetaData[] relatedMmds = ownerMemberMetaData.getRelatedMemberMetaData(ec.getClassLoaderResolver());
        Object elementColl = elementOP.provideField(relatedMmds[0].getAbsoluteFieldNumber());
        if (elementColl != null && elementColl instanceof Collection && elementColl instanceof SCO && ((Collection) elementColl).contains(ownerOP.getObject())) {
            NucleusLogger.DATASTORE.info(Localiser.msg("056040", ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerOP.getObject()), element));
            return true;
        }
    } else {
        // Element is still detached
        if (locate(ownerOP, element)) {
            NucleusLogger.DATASTORE.info(Localiser.msg("056040", ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerOP.getObject()), element));
            return true;
        }
    }
    return false;
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) SCO(org.datanucleus.store.types.SCO)

Example 2 with SCO

use of org.datanucleus.store.types.SCO in project datanucleus-rdbms by datanucleus.

the class CollectionMapping method preDelete.

/**
 * Method to be called before any delete of the owner class element.
 * @param ownerSM StateManager of the owner
 */
public void preDelete(DNStateManager ownerSM) {
    if (containerIsStoredInSingleColumn()) {
        // Field is stored with the main object so nothing to clean up
        return;
    }
    // makes sure field is loaded
    ownerSM.isLoaded(getAbsoluteFieldNumber());
    Collection value = (Collection) ownerSM.provideField(getAbsoluteFieldNumber());
    if (value == null) {
        return;
    }
    ExecutionContext ec = ownerSM.getExecutionContext();
    boolean dependent = mmd.getCollection().isDependentElement();
    if (mmd.isCascadeRemoveOrphans()) {
        dependent = true;
    }
    boolean hasJoin = (mmd.getJoinMetaData() != null);
    boolean hasFK = false;
    if (!hasJoin) {
        if (mmd.getElementMetaData() != null && mmd.getElementMetaData().getForeignKeyMetaData() != null) {
            // FK collection, using <element> FK spec
            hasFK = true;
        } else if (mmd.getForeignKeyMetaData() != null) {
            // FK collection, using <field> FK spec
            hasFK = true;
        }
        AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver());
        if (relatedMmds != null && relatedMmds[0].getForeignKeyMetaData() != null) {
            // FK collection (bidir), using <field> FK spec at other end
            hasFK = true;
        }
    }
    if (ec.getStringProperty(PropertyNames.PROPERTY_DELETION_POLICY).equals("JDO2")) {
        // JDO doesn't currently take note of foreign-key
        hasFK = false;
    }
    if (ec.getManageRelations()) {
        ec.getRelationshipManager(ownerSM).relationChange(getAbsoluteFieldNumber(), value, null);
    }
    // TODO Why dont we just do clear here always ? The backing store should take care of if nulling or deleting etc
    if (dependent || hasJoin || !hasFK) {
        // or there are no FKs specified (in which case we need to clean up)
        if (!(value instanceof SCO)) {
            value = (Collection) SCOUtils.wrapSCOField(ownerSM, getAbsoluteFieldNumber(), value, true);
        }
        value.clear();
        // Flush any outstanding updates
        ec.flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerSM);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) SCO(org.datanucleus.store.types.SCO) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO)

Example 3 with SCO

use of org.datanucleus.store.types.SCO in project datanucleus-rdbms by datanucleus.

the class ArrayMapping method postInsert.

// ---------------------- Implementation of MappingCallbacks ----------------------------------
/**
 * Method to be called after the insert of the owner class element.
 * @param ownerSM StateManager of the owner
 */
public void postInsert(DNStateManager ownerSM) {
    ExecutionContext ec = ownerSM.getExecutionContext();
    Object value = ownerSM.provideField(getAbsoluteFieldNumber());
    if (value == null) {
        return;
    }
    if (containerIsStoredInSingleColumn()) {
        if (mmd.getArray().elementIsPersistent()) {
            // Make sure all persistable elements have StateManagers
            Object[] arrElements = (Object[]) value;
            for (Object elem : arrElements) {
                if (elem != null) {
                    DNStateManager elemSM = ec.findStateManager(elem);
                    if (elemSM == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
                        elemSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, elem, false, ownerSM, mmd.getAbsoluteFieldNumber(), PersistableObjectType.EMBEDDED_ARRAY_ELEMENT_PC);
                    }
                }
            }
        }
        return;
    }
    int arrayLength = Array.getLength(value);
    boolean persistentElements = (mmd.getRelationType(ec.getClassLoaderResolver()) != RelationType.NONE);
    boolean needsAttaching = false;
    if (persistentElements) {
        Object[] array = (Object[]) value;
        if (!mmd.isCascadePersist()) {
            // Check that all elements are persistent before continuing and throw exception if necessary
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("007006", mmd.getFullFieldName()));
            }
            for (int i = 0; i < arrayLength; i++) {
                if (!ec.getApiAdapter().isDetached(array[i]) && !ec.getApiAdapter().isPersistent(array[i])) {
                    // Element is not persistent so throw exception
                    throw new ReachableObjectNotCascadedException(mmd.getFullFieldName(), array[i]);
                }
            }
        } else {
            // Reachability
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("007007", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
            }
        }
        for (int i = 0; i < arrayLength; i++) {
            if (ec.getApiAdapter().isDetached(array[i])) {
                needsAttaching = true;
                break;
            }
        }
    }
    if (needsAttaching) {
        // Create a wrapper and attach the elements (and add the others)
        SCO collWrapper = replaceFieldWithWrapper(ownerSM, null);
        if (arrayLength > 0) {
            collWrapper.attachCopy(value);
            // The attach will have put entries in the operationQueue if using optimistic, so flush them
            ec.flushOperationsForBackingStore(((BackedSCO) collWrapper).getBackingStore(), ownerSM);
        }
    } else {
        if (arrayLength > 0) {
            // Add the elements direct to the datastore
            ((ArrayStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).set(ownerSM, value);
        }
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) DNStateManager(org.datanucleus.state.DNStateManager) ArrayStore(org.datanucleus.store.types.scostore.ArrayStore) SCO(org.datanucleus.store.types.SCO) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO) ReachableObjectNotCascadedException(org.datanucleus.exceptions.ReachableObjectNotCascadedException)

Example 4 with SCO

use of org.datanucleus.store.types.SCO in project datanucleus-rdbms by datanucleus.

the class MapMapping method preDelete.

/**
 * Method to be called before any delete of the owner class element.
 * @param ownerSM StateManager of the owner
 */
public void preDelete(DNStateManager ownerSM) {
    if (containerIsStoredInSingleColumn()) {
        // Do nothing when serialised since we are handled in the main request
        return;
    }
    // makes sure field is loaded
    ownerSM.isLoaded(getAbsoluteFieldNumber());
    java.util.Map value = (java.util.Map) ownerSM.provideField(getAbsoluteFieldNumber());
    if (value == null) {
        // Do nothing
        return;
    }
    if (!(value instanceof SCO)) {
        // Make sure we have a SCO wrapper so we can clear from the datastore
        value = (java.util.Map) SCOUtils.wrapSCOField(ownerSM, mmd.getAbsoluteFieldNumber(), value, true);
    }
    value.clear();
    // Flush any outstanding updates for this backing store
    ownerSM.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerSM);
}
Also used : Map(java.util.Map) Map(java.util.Map) SCO(org.datanucleus.store.types.SCO) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO)

Example 5 with SCO

use of org.datanucleus.store.types.SCO in project datanucleus-rdbms by datanucleus.

the class JoinSetStore method elementAlreadyContainsOwnerInMtoN.

/**
 * Convenience method to check if an element already refers to the owner in an M-N relation (i.e added from other side).
 * @param ownerSM StateManager of the owner
 * @param element The element
 * @return Whether the element contains the owner
 */
private boolean elementAlreadyContainsOwnerInMtoN(DNStateManager ownerSM, Object element) {
    ExecutionContext ec = ownerSM.getExecutionContext();
    if (ec.getOperationQueue() != null) {
        // TODO This means we always do a "SELECT 1 FROM JOINTABLE" for every addition when optimistic. Should seek to avoid this by updates to operationQueue maybe
        if (locate(ownerSM, element)) {
            NucleusLogger.DATASTORE.info(Localiser.msg("056040", ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerSM.getObject()), element));
            return true;
        }
        return false;
    }
    DNStateManager elementSM = ec.findStateManager(element);
    if (elementSM != null) {
        // Check the collection at the other side whether already added (to avoid the locate call)
        AbstractMemberMetaData[] relatedMmds = ownerMemberMetaData.getRelatedMemberMetaData(ec.getClassLoaderResolver());
        Object elementColl = elementSM.provideField(relatedMmds[0].getAbsoluteFieldNumber());
        if (elementColl != null && elementColl instanceof Collection && elementColl instanceof SCO && ((Collection) elementColl).contains(ownerSM.getObject())) {
            NucleusLogger.DATASTORE.info(Localiser.msg("056040", ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerSM.getObject()), element));
            return true;
        }
    } else {
        // Element is still detached
        if (locate(ownerSM, element)) {
            NucleusLogger.DATASTORE.info(Localiser.msg("056040", ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(ownerSM.getObject()), element));
            return true;
        }
    }
    return false;
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) DNStateManager(org.datanucleus.state.DNStateManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) SCO(org.datanucleus.store.types.SCO)

Aggregations

SCO (org.datanucleus.store.types.SCO)17 ExecutionContext (org.datanucleus.ExecutionContext)9 BackedSCO (org.datanucleus.store.types.wrappers.backed.BackedSCO)8 Collection (java.util.Collection)7 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)7 ReachableObjectNotCascadedException (org.datanucleus.exceptions.ReachableObjectNotCascadedException)4 RelationType (org.datanucleus.metadata.RelationType)4 ObjectProvider (org.datanucleus.state.ObjectProvider)4 Map (java.util.Map)3 ApiAdapter (org.datanucleus.api.ApiAdapter)3 DNStateManager (org.datanucleus.state.DNStateManager)3 TypeManager (org.datanucleus.store.types.TypeManager)3 ContainerHandler (org.datanucleus.store.types.ContainerHandler)2 ArrayStore (org.datanucleus.store.types.scostore.ArrayStore)2 CollectionStore (org.datanucleus.store.types.scostore.CollectionStore)2 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)1 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)1 ContainerAdapter (org.datanucleus.store.types.ContainerAdapter)1 SCOContainer (org.datanucleus.store.types.SCOContainer)1