Search in sources :

Example 1 with CollectionStore

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

the class CollectionMapping method postUpdate.

/**
 * Method to be called after any update of the owner class element.
 * This method could be called in two situations
 * <ul>
 * <li>Update a collection field of an object by replacing the collection with a new collection, so UpdateRequest is called, which calls here</li>
 * <li>Persist a new object, and it needed to wait til the element was inserted so goes into dirty state and then flush() triggers UpdateRequest, which comes here</li>
 * </ul>
 * @param ownerOP ObjectProvider of the owner
 */
public void postUpdate(ObjectProvider ownerOP) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    Collection value = (Collection) ownerOP.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have ObjectProviders
                Object[] collElements = value.toArray();
                for (Object collElement : collElements) {
                    if (collElement != null) {
                        ObjectProvider elemOP = ec.findObjectProvider(collElement);
                        if (elemOP == null || ec.getApiAdapter().getExecutionContext(collElement) == null) {
                            elemOP = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, collElement, false, ownerOP, mmd.getAbsoluteFieldNumber());
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // remove any elements in the collection and replace it with an empty SCO wrapper
        ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerOP);
        replaceFieldWithWrapper(ownerOP, null);
        return;
    }
    if (value instanceof BackedSCO) {
        // Already have a SCO value, so flush outstanding updates
        ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
        return;
    }
    if (mmd.isCascadeUpdate()) {
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", mmd.getFullFieldName()));
        }
        CollectionStore backingStore = ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
        backingStore.update(ownerOP, value);
        // Replace the field with a wrapper containing these elements
        replaceFieldWithWrapper(ownerOP, value);
    } else {
        // User doesn't want to update by reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
        }
        return;
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) ObjectProvider(org.datanucleus.state.ObjectProvider) CollectionStore(org.datanucleus.store.types.scostore.CollectionStore) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO)

Example 2 with CollectionStore

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

the class CollectionMapping method postInsert.

/**
 * Method to be called after the insert of the owner class element.
 * @param ownerOP ObjectProvider of the owner
 */
public void postInsert(ObjectProvider ownerOP) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    Collection value = (Collection) ownerOP.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have ObjectProviders
                Object[] collElements = value.toArray();
                for (Object elem : collElements) {
                    if (elem != null) {
                        ObjectProvider elemOP = ec.findObjectProvider(elem);
                        if (elemOP == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
                            elemOP = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, elem, false, ownerOP, mmd.getAbsoluteFieldNumber());
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // replace null collections with an empty SCO wrapper
        replaceFieldWithWrapper(ownerOP, null);
        return;
    }
    Object[] collElements = value.toArray();
    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 (Object collElement : collElements) {
            if (!ec.getApiAdapter().isDetached(collElement) && !ec.getApiAdapter().isPersistent(collElement)) {
                // Element is not persistent so throw exception
                throw new ReachableObjectNotCascadedException(mmd.getFullFieldName(), collElement);
            }
        }
    } else {
        // Reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007007", mmd.getFullFieldName()));
        }
    }
    // Check if some elements need attaching
    // TODO Investigate if we can just use the attachCopy route below and skip off this check
    boolean needsAttaching = false;
    for (Object collElement : collElements) {
        if (ownerOP.getExecutionContext().getApiAdapter().isDetached(collElement)) {
            needsAttaching = true;
            break;
        }
    }
    if (needsAttaching) {
        // Create a wrapper and attach the elements (and add the others)
        SCO collWrapper = replaceFieldWithWrapper(ownerOP, null);
        if (value.size() > 0) {
            collWrapper.attachCopy(value);
            // The attach will have put entries in the operationQueue if using optimistic, so flush them
            ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) collWrapper).getBackingStore(), ownerOP);
        }
    } else {
        if (value.size() > 0) {
            // Add the elements direct to the datastore
            ((CollectionStore) storeMgr.getBackingStoreForField(ownerOP.getExecutionContext().getClassLoaderResolver(), mmd, value.getClass())).addAll(ownerOP, value, 0);
            // Create a SCO wrapper with the elements loaded
            replaceFieldWithWrapper(ownerOP, value);
        } else {
            if (mmd.getRelationType(ownerOP.getExecutionContext().getClassLoaderResolver()) == RelationType.MANY_TO_MANY_BI) {
                // Create a SCO wrapper, pass in null so it loads any from the datastore (on other side?)
                replaceFieldWithWrapper(ownerOP, null);
            } else {
                // Create a SCO wrapper, pass in empty collection to avoid loading from DB (extra SQL)
                replaceFieldWithWrapper(ownerOP, value);
            }
        }
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) ObjectProvider(org.datanucleus.state.ObjectProvider) CollectionStore(org.datanucleus.store.types.scostore.CollectionStore) SCO(org.datanucleus.store.types.SCO) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO) ReachableObjectNotCascadedException(org.datanucleus.exceptions.ReachableObjectNotCascadedException)

Example 3 with CollectionStore

use of org.datanucleus.store.types.scostore.CollectionStore in project datanucleus-core by datanucleus.

the class SCOUtils method populateMapDelegateWithStoreData.

/**
 * Convenience method to populate the passed delegate Map with the keys/values from the associated Store.
 * <P>
 * The issue here is that we need to load the keys and values in as few calls as possible. The method
 * employed here reads in the keys (if persistable), then the values (if persistable), and then the
 * "entries" (ids of keys and values) so we can associate the keys to the values.
 * @param delegate The delegate
 * @param store The Store
 * @param ownerOP ObjectProvider of the owner of the map.
 */
public static void populateMapDelegateWithStoreData(Map delegate, MapStore store, ObjectProvider ownerOP) {
    // If we have persistable keys then load them. The keys query will pull in the key fetch plan
    // so this instantiates them in the cache
    java.util.Set keys = new java.util.HashSet();
    if (!store.keysAreEmbedded() && !store.keysAreSerialised()) {
        // Retrieve the persistable keys
        SetStore keystore = store.keySetStore();
        Iterator keyIter = keystore.iterator(ownerOP);
        while (keyIter.hasNext()) {
            keys.add(keyIter.next());
        }
    }
    // If we have persistable values then load them. The values query will pull in the value fetch plan
    // so this instantiates them in the cache
    java.util.List values = new java.util.ArrayList();
    if (!store.valuesAreEmbedded() && !store.valuesAreSerialised()) {
        // Retrieve the persistable values
        CollectionStore valuestore = store.valueCollectionStore();
        Iterator valueIter = valuestore.iterator(ownerOP);
        while (valueIter.hasNext()) {
            values.add(valueIter.next());
        }
    }
    // Retrieve the entries (key-value pairs so we can associate them)
    // TODO Ultimately would like to just call this, but the entry query can omit the inheritance level of a key or value
    SetStore entries = store.entrySetStore();
    Iterator entryIter = entries.iterator(ownerOP);
    while (entryIter.hasNext()) {
        Map.Entry entry = (Map.Entry) entryIter.next();
        Object key = entry.getKey();
        Object value = entry.getValue();
        delegate.put(key, value);
    }
    if (!store.keysAreEmbedded() && !store.keysAreSerialised() && delegate.size() != keys.size()) {
        // With Derby 10.x we can get instances where the values query returns no values yet entries is not empty TODO Maybe make this throw an exception
        NucleusLogger.DATASTORE_RETRIEVE.warn("The number of Map key objects (" + keys.size() + ")" + " was different to the number of entries (" + delegate.size() + ")." + " Likely there is a bug in your datastore");
    }
    if (!store.valuesAreEmbedded() && !store.valuesAreSerialised() && delegate.size() != values.size()) {
        // With Derby 10.x we can get instances where the values query returns no values yet entries is not empty TODO Maybe make this throw an exception
        NucleusLogger.DATASTORE_RETRIEVE.warn("The number of Map value objects (" + values.size() + ")" + " was different to the number of entries (" + delegate.size() + ")." + " Likely there is a bug in your datastore, or you have null values?");
    }
    keys.clear();
    values.clear();
}
Also used : ArrayList(java.util.ArrayList) Set(java.util.Set) SetStore(org.datanucleus.store.types.scostore.SetStore) List(java.util.List) Iterator(java.util.Iterator) CollectionStore(org.datanucleus.store.types.scostore.CollectionStore) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) HashSet(java.util.HashSet)

Example 4 with CollectionStore

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

the class CollectionMapping method postUpdate.

/**
 * Method to be called after any update of the owner class element.
 * This method could be called in two situations
 * <ul>
 * <li>Update a collection field of an object by replacing the collection with a new collection, so UpdateRequest is called, which calls here</li>
 * <li>Persist a new object, and it needed to wait til the element was inserted so goes into dirty state and then flush() triggers UpdateRequest, which comes here</li>
 * </ul>
 * @param ownerSM StateManager of the owner
 */
public void postUpdate(DNStateManager ownerSM) {
    ExecutionContext ec = ownerSM.getExecutionContext();
    Collection value = (Collection) ownerSM.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have StateManagers
                Object[] collElements = value.toArray();
                for (Object collElement : collElements) {
                    if (collElement != null) {
                        DNStateManager elemSM = ec.findStateManager(collElement);
                        if (elemSM == null || ec.getApiAdapter().getExecutionContext(collElement) == null) {
                            elemSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, collElement, false, ownerSM, mmd.getAbsoluteFieldNumber(), PersistableObjectType.EMBEDDED_COLLECTION_ELEMENT_PC);
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // remove any elements in the collection and replace it with an empty SCO wrapper
        ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerSM);
        replaceFieldWithWrapper(ownerSM, null);
        return;
    }
    if (value instanceof BackedSCO) {
        // Already have a SCO value, so flush outstanding updates
        ec.flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerSM);
        return;
    }
    if (mmd.isCascadePersist()) {
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
        }
        CollectionStore backingStore = ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
        backingStore.update(ownerSM, value);
        // Replace the field with a wrapper containing these elements
        replaceFieldWithWrapper(ownerSM, value);
    } else {
        // User doesn't want to update by reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
        }
        return;
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) DNStateManager(org.datanucleus.state.DNStateManager) CollectionStore(org.datanucleus.store.types.scostore.CollectionStore) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO)

Example 5 with CollectionStore

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

the class CollectionMapping 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();
    Collection value = (Collection) ownerSM.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have StateManagers
                Object[] collElements = value.toArray();
                for (Object elem : collElements) {
                    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_COLLECTION_ELEMENT_PC);
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // replace null collections with an empty SCO wrapper
        replaceFieldWithWrapper(ownerSM, null);
        return;
    }
    Object[] collElements = value.toArray();
    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 (Object collElement : collElements) {
            if (!ec.getApiAdapter().isDetached(collElement) && !ec.getApiAdapter().isPersistent(collElement)) {
                // Element is not persistent so throw exception
                throw new ReachableObjectNotCascadedException(mmd.getFullFieldName(), collElement);
            }
        }
    } else {
        // Reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007007", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
        }
    }
    // Check if some elements need attaching
    // TODO Investigate if we can just use the attachCopy route below and skip off this check
    boolean needsAttaching = false;
    for (Object collElement : collElements) {
        if (ec.getApiAdapter().isDetached(collElement)) {
            needsAttaching = true;
            break;
        }
    }
    if (needsAttaching) {
        // Create a wrapper and attach the elements (and add the others)
        SCO collWrapper = replaceFieldWithWrapper(ownerSM, null);
        if (value.size() > 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 (value.size() > 0) {
            // Add the elements direct to the datastore
            ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass())).addAll(ownerSM, value, 0);
            // Create a SCO wrapper with the elements loaded
            replaceFieldWithWrapper(ownerSM, value);
        } else {
            if (mmd.getRelationType(ec.getClassLoaderResolver()) == RelationType.MANY_TO_MANY_BI) {
                // Create a SCO wrapper, pass in null so it loads any from the datastore (on other side?)
                replaceFieldWithWrapper(ownerSM, null);
            } else {
                // Create a SCO wrapper, pass in empty collection to avoid loading from DB (extra SQL)
                replaceFieldWithWrapper(ownerSM, value);
            }
        }
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) DNStateManager(org.datanucleus.state.DNStateManager) CollectionStore(org.datanucleus.store.types.scostore.CollectionStore) SCO(org.datanucleus.store.types.SCO) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO) ReachableObjectNotCascadedException(org.datanucleus.exceptions.ReachableObjectNotCascadedException)

Aggregations

CollectionStore (org.datanucleus.store.types.scostore.CollectionStore)5 Collection (java.util.Collection)4 ExecutionContext (org.datanucleus.ExecutionContext)4 BackedSCO (org.datanucleus.store.types.wrappers.backed.BackedSCO)4 ReachableObjectNotCascadedException (org.datanucleus.exceptions.ReachableObjectNotCascadedException)2 DNStateManager (org.datanucleus.state.DNStateManager)2 ObjectProvider (org.datanucleus.state.ObjectProvider)2 SCO (org.datanucleus.store.types.SCO)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1 SetStore (org.datanucleus.store.types.scostore.SetStore)1