use of org.datanucleus.store.types.wrappers.backed.BackedSCO 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.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.
the class MapMapping method postUpdate.
/**
* Method to be called after any update of the owner class element.
* @param ownerOP ObjectProvider of the owner
*/
public void postUpdate(ObjectProvider ownerOP) {
ExecutionContext ec = ownerOP.getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
java.util.Map value = (java.util.Map) ownerOP.provideField(getAbsoluteFieldNumber());
if (containerIsStoredInSingleColumn()) {
// Do nothing when serialised since we are handled in the main request
if (value != null) {
if (mmd.getMap().keyIsPersistent() || mmd.getMap().valueIsPersistent()) {
// Make sure all persistable keys/values have ObjectProviders
Set entries = value.entrySet();
Iterator iter = entries.iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (mmd.getMap().keyIsPersistent() && entry.getKey() != null) {
Object key = entry.getKey();
if (ec.findObjectProvider(key) == null || ec.getApiAdapter().getExecutionContext(key) == null) {
ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, key, false, ownerOP, mmd.getAbsoluteFieldNumber());
}
}
if (mmd.getMap().valueIsPersistent() && entry.getValue() != null) {
Object val = entry.getValue();
if (ec.findObjectProvider(val) == null || ec.getApiAdapter().getExecutionContext(val) == null) {
ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, val, false, ownerOP, mmd.getAbsoluteFieldNumber());
}
}
}
}
}
return;
}
if (value == null) {
// remove any entries in the map and replace it with an empty SCO wrapper
((MapStore) 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()));
}
// Update the datastore with this value of map (clear old entries and add new ones)
// This method could be called in two situations
// 1). Update a map field of an object, so UpdateRequest is called, which calls here
// 2). 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
MapStore store = ((MapStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
// TODO Consider making this more efficient picking the ones to remove/add
// e.g use an update() method on the backing store like for CollectionStore
store.clear(ownerOP);
store.putAll(ownerOP, value);
// Replace the field with a wrapper containing these entries
replaceFieldWithWrapper(ownerOP, value);
} else {
// User doesnt want to update by reachability
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
}
return;
}
}
use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.
the class FKListStore method set.
/**
* Method to set an object in the List at a position.
* @param ownerOP ObjectProvider for the owner
* @param index The item index
* @param element What to set it to.
* @param allowDependentField Whether to enable dependent-field deletes during the set
* @return The value before setting.
*/
public E set(ObjectProvider ownerOP, int index, Object element, boolean allowDependentField) {
// Last argument means don't set the position on any INSERT
validateElementForWriting(ownerOP, element, -1);
// Find the original element at this position
E oldElement = null;
List fieldVal = (List) ownerOP.provideField(ownerMemberMetaData.getAbsoluteFieldNumber());
if (fieldVal != null && fieldVal instanceof BackedSCO && ((BackedSCO) fieldVal).isLoaded()) {
// Already loaded in the wrapper
oldElement = (E) fieldVal.get(index);
} else {
oldElement = get(ownerOP, index);
}
ManagedConnection mconn = null;
try {
ExecutionContext ec = ownerOP.getExecutionContext();
SQLController sqlControl = storeMgr.getSQLController();
mconn = storeMgr.getConnectionManager().getConnection(ec);
// Unset the existing object from this position
String theUnsetStmt = getUnsetStmt();
try {
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, theUnsetStmt, false);
try {
int jdbcPosition = 1;
jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
if (orderMapping != null) {
jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, orderMapping);
}
if (relationDiscriminatorMapping != null) {
jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
}
sqlControl.executeStatementUpdate(ec, mconn, theUnsetStmt, ps, true);
} finally {
sqlControl.closeStatement(mconn, ps);
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056015", theUnsetStmt), e);
} finally {
}
// Set the new object at this position
String theSetStmt = getSetStmt(element);
try {
PreparedStatement ps2 = sqlControl.getStatementForUpdate(mconn, theSetStmt, false);
try {
ComponentInfo elemInfo = getComponentInfoForElement(element);
JavaTypeMapping elemMapping = this.elementMapping;
JavaTypeMapping orderMapping = this.orderMapping;
if (elemInfo != null) {
elemMapping = elemInfo.getDatastoreClass().getIdMapping();
orderMapping = elemInfo.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_INDEX);
}
int jdbcPosition = 1;
jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps2, jdbcPosition, this);
if (orderMapping != null) {
jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps2, index, jdbcPosition, orderMapping);
}
if (relationDiscriminatorMapping != null) {
jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps2, jdbcPosition, this);
}
jdbcPosition = BackingStoreHelper.populateElementForWhereClauseInStatement(ec, ps2, element, jdbcPosition, elemMapping);
sqlControl.executeStatementUpdate(ec, mconn, theSetStmt, ps2, true);
} finally {
sqlControl.closeStatement(mconn, ps2);
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056015", theSetStmt), e);
}
} finally {
if (mconn != null) {
mconn.release();
}
}
// Dependent field
boolean dependent = getOwnerMemberMetaData().getCollection().isDependentElement();
if (getOwnerMemberMetaData().isCascadeRemoveOrphans()) {
dependent = true;
}
if (dependent && allowDependentField) {
if (oldElement != null) {
// Delete the element if it is dependent and doesnt have a duplicate entry in the list
ownerOP.getExecutionContext().deleteObjectInternal(oldElement);
}
}
return oldElement;
}
use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.
the class JoinListStore method set.
/**
* Method to set an object in the List.
* @param op ObjectProvider for the owner
* @param index The item index
* @param element What to set it to.
* @param allowDependentField Whether to allow dependent field deletes
* @return The value before setting.
*/
public E set(ObjectProvider op, int index, Object element, boolean allowDependentField) {
ExecutionContext ec = op.getExecutionContext();
validateElementForWriting(ec, element, null);
// Find the original element at this position
E oldElement = null;
List fieldVal = (List) op.provideField(ownerMemberMetaData.getAbsoluteFieldNumber());
if (fieldVal != null && fieldVal instanceof BackedSCO && ((BackedSCO) fieldVal).isLoaded()) {
// Already loaded in the wrapper
oldElement = (E) fieldVal.get(index);
} else {
oldElement = get(op, index);
}
// Check for dynamic schema updates prior to update
if (storeMgr.getBooleanObjectProperty(RDBMSPropertyNames.PROPERTY_RDBMS_DYNAMIC_SCHEMA_UPDATES).booleanValue()) {
DynamicSchemaFieldManager dynamicSchemaFM = new DynamicSchemaFieldManager(storeMgr, op);
Collection coll = new ArrayList();
coll.add(element);
dynamicSchemaFM.storeObjectField(getOwnerMemberMetaData().getAbsoluteFieldNumber(), coll);
if (dynamicSchemaFM.hasPerformedSchemaUpdates()) {
setStmt = null;
}
}
String theSetStmt = getSetStmt();
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, theSetStmt, false);
try {
int jdbcPosition = 1;
jdbcPosition = BackingStoreHelper.populateElementInStatement(ec, ps, element, jdbcPosition, elementMapping);
jdbcPosition = BackingStoreHelper.populateOwnerInStatement(op, ec, ps, jdbcPosition, this);
if (getOwnerMemberMetaData().getOrderMetaData() != null && !getOwnerMemberMetaData().getOrderMetaData().isIndexedList()) {
// Ordered list, so can't easily do a set!!!
NucleusLogger.PERSISTENCE.warn("Calling List.addElement at a position for an ordered list is a stupid thing to do; the ordering is set my the ordering specification. Use an indexed list to do this correctly");
} else {
jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, orderMapping);
}
if (relationDiscriminatorMapping != null) {
jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
}
sqlControl.executeStatementUpdate(ec, mconn, theSetStmt, ps, true);
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056015", theSetStmt), e);
}
// Dependent field
CollectionMetaData collmd = ownerMemberMetaData.getCollection();
boolean dependent = collmd.isDependentElement();
if (ownerMemberMetaData.isCascadeRemoveOrphans()) {
dependent = true;
}
if (dependent && !collmd.isEmbeddedElement() && allowDependentField) {
if (oldElement != null && !contains(op, oldElement)) {
// Delete the element if it is dependent and doesn't have a duplicate entry in the list
ec.deleteObjectInternal(oldElement);
}
}
return oldElement;
}
use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.
the class CollectionMapping method preDelete.
/**
* Method to be called before any delete of the owner class element.
* @param ownerOP ObjectProvider of the owner
*/
public void preDelete(ObjectProvider ownerOP) {
if (containerIsStoredInSingleColumn()) {
// Field is stored with the main object so nothing to clean up
return;
}
// makes sure field is loaded
ownerOP.isLoaded(getAbsoluteFieldNumber());
Collection value = (Collection) ownerOP.provideField(getAbsoluteFieldNumber());
if (value == null) {
return;
}
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(ownerOP.getExecutionContext().getClassLoaderResolver());
if (relatedMmds != null && relatedMmds[0].getForeignKeyMetaData() != null) {
// FK collection (bidir), using <field> FK spec at other end
hasFK = true;
}
}
if (ownerOP.getExecutionContext().getStringProperty(PropertyNames.PROPERTY_DELETION_POLICY).equals("JDO2")) {
// JDO doesn't currently take note of foreign-key
hasFK = false;
}
if (ownerOP.getExecutionContext().getManageRelations()) {
ownerOP.getExecutionContext().getRelationshipManager(ownerOP).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(ownerOP, getAbsoluteFieldNumber(), value, true);
}
value.clear();
// Flush any outstanding updates
ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
}
}
Aggregations