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