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;
}
}
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);
}
}
}
}
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();
}
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;
}
}
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);
}
}
}
}
Aggregations