use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class FKListStore method clear.
/**
* Method to clear the List.
* This is called by the List.clear() method, or when the container object is being deleted
* and the elements are to be removed (maybe for dependent field), or also when updating a Collection
* and removing all existing prior to adding all new.
* @param ownerOP ObjectProvider for the owner
*/
public void clear(ObjectProvider ownerOP) {
boolean deleteElements = false;
ExecutionContext ec = ownerOP.getExecutionContext();
boolean dependent = ownerMemberMetaData.getCollection().isDependentElement();
if (ownerMemberMetaData.isCascadeRemoveOrphans()) {
dependent = true;
}
if (dependent) {
// Elements are dependent and can't exist on their own, so delete them all
NucleusLogger.DATASTORE.debug(Localiser.msg("056034"));
deleteElements = true;
} else {
if (ownerMapping.isNullable() && orderMapping == null) {
// Field is not dependent, and nullable so we null the FK
NucleusLogger.DATASTORE.debug(Localiser.msg("056036"));
deleteElements = false;
} else if (ownerMapping.isNullable() && orderMapping != null && orderMapping.isNullable()) {
// Field is not dependent, and nullable so we null the FK
NucleusLogger.DATASTORE.debug(Localiser.msg("056036"));
deleteElements = false;
} else {
// Field is not dependent, and not nullable so we just delete the elements
NucleusLogger.DATASTORE.debug(Localiser.msg("056035"));
deleteElements = true;
}
}
if (deleteElements) {
// Find elements present in the datastore and delete them one-by-one
Iterator elementsIter = iterator(ownerOP);
if (elementsIter != null) {
while (elementsIter.hasNext()) {
Object element = elementsIter.next();
if (ec.getApiAdapter().isPersistable(element) && ec.getApiAdapter().isDeleted(element)) {
// Element is waiting to be deleted so flush it (it has the FK)
ObjectProvider objSM = ec.findObjectProvider(element);
objSM.flush();
} else {
// Element not yet marked for deletion so go through the normal process
ec.deleteObjectInternal(element);
}
}
}
} else {
boolean ownerSoftDelete = ownerOP.getClassMetaData().hasExtension(MetaData.EXTENSION_CLASS_SOFTDELETE);
if (!ownerSoftDelete) {
// Clear without delete
// TODO If the relation is bidirectional we need to clear the owner in the element
String clearNullifyStmt = getClearNullifyStmt();
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, clearNullifyStmt, false);
try {
int jdbcPosition = 1;
jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
if (relationDiscriminatorMapping != null) {
BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
}
sqlControl.executeStatementUpdate(ec, mconn, clearNullifyStmt, ps, true);
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056013", clearNullifyStmt), e);
}
}
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class FKListStore method internalRemove.
/**
* Convenience method to remove the specified element from the List.
* @param ownerOP ObjectProvider for the owner
* @param element The element
* @return Whether the List was modified
*/
protected boolean internalRemove(ObjectProvider ownerOP, Object element, int size) {
if (indexedList) {
// Indexed List
// The element can be at one position only (no duplicates allowed in FK list)
int index = indexOf(ownerOP, element);
if (index == -1) {
return false;
}
internalRemoveAt(ownerOP, index, size);
} else {
// Ordered List - no index so null the FK (if nullable) or delete the element
if (ownerMapping.isNullable()) {
// Nullify the FK
ExecutionContext ec = ownerOP.getExecutionContext();
ObjectProvider elementSM = ec.findObjectProvider(element);
if (relationType == RelationType.ONE_TO_MANY_BI) {
// Set field in element to null (so it nulls the FK)
// TODO This is ManagedRelations - move into RelationshipManager
elementSM.replaceFieldMakeDirty(ownerMemberMetaData.getRelatedMemberMetaData(clr)[0].getAbsoluteFieldNumber(), null);
if (ownerOP.getExecutionContext().isFlushing()) {
elementSM.flush();
}
} else {
// Null the (external) FK in the element
updateElementFk(ownerOP, element, null, -1);
}
} else {
// Delete the element
ownerOP.getExecutionContext().deleteObjectInternal(element);
}
}
return true;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class FKMapStore method remove.
/**
* Method to remove an entry from the map.
* @param op ObjectProvider for the map.
* @param key Key of the entry to remove.
* @return The value that was removed.
*/
public V remove(ObjectProvider op, Object key, Object oldValue) {
ExecutionContext ec = op.getExecutionContext();
if (keyFieldNumber >= 0) {
// Key stored in value
if (oldValue != null) {
boolean deletingValue = false;
ObjectProvider valueOP = ec.findObjectProvider(oldValue);
if (ownerMemberMetaData.getMap().isDependentValue()) {
// Delete the value if it is dependent
deletingValue = true;
ec.deleteObjectInternal(oldValue);
valueOP.flush();
} else if (ownerMapping.isNullable()) {
// Null the owner FK
if (ownerFieldNumber >= 0) {
// Update the field in the value
Object oldOwner = valueOP.provideField(ownerFieldNumber);
valueOP.replaceFieldMakeDirty(ownerFieldNumber, null);
valueOP.flush();
if (ec.getManageRelations()) {
ec.getRelationshipManager(valueOP).relationChange(ownerFieldNumber, oldOwner, null);
}
} else {
// Update the external FK in the value in the datastore
updateValueFkInternal(op, oldValue, null);
}
} else {
// Not nullable, so must delete since no other way of removing from map
deletingValue = true;
ec.deleteObjectInternal(oldValue);
valueOP.flush();
}
if (ownerMemberMetaData.getMap().isDependentKey()) {
// Delete the key since it is dependent
if (!deletingValue) {
// Null FK in value to key
if (keyMapping.isNullable()) {
valueOP.replaceFieldMakeDirty(keyFieldNumber, null);
valueOP.flush();
if (ec.getManageRelations()) {
ec.getRelationshipManager(valueOP).relationChange(keyFieldNumber, key, null);
}
}
}
ec.deleteObjectInternal(key);
ObjectProvider keyOP = ec.findObjectProvider(key);
keyOP.flush();
}
}
} else {
// Value stored in key
if (key != null) {
boolean deletingKey = false;
ObjectProvider keyOP = ec.findObjectProvider(key);
if (ownerMemberMetaData.getMap().isDependentKey()) {
// Delete the key if it is dependent
deletingKey = true;
ec.deleteObjectInternal(key);
keyOP.flush();
} else if (ownerMapping.isNullable()) {
// Null the owner FK
if (ownerFieldNumber >= 0) {
// Update the field in the key
Object oldOwner = keyOP.provideField(ownerFieldNumber);
keyOP.replaceFieldMakeDirty(ownerFieldNumber, null);
keyOP.flush();
if (ec.getManageRelations()) {
ec.getRelationshipManager(keyOP).relationChange(ownerFieldNumber, oldOwner, null);
}
} else {
// Update the external FK in the key in the datastore
updateKeyFkInternal(op, key, null);
}
} else {
// Not nullable, so must delete since no other way of removing from map
deletingKey = true;
ec.deleteObjectInternal(key);
keyOP.flush();
}
if (ownerMemberMetaData.getMap().isDependentValue()) {
// Delete the value since it is dependent
if (!deletingKey) {
// Null FK in key to value
if (valueMapping.isNullable()) {
keyOP.replaceFieldMakeDirty(valueFieldNumber, null);
keyOP.flush();
if (ec.getManageRelations()) {
ec.getRelationshipManager(keyOP).relationChange(valueFieldNumber, oldValue, null);
}
}
}
ec.deleteObjectInternal(oldValue);
ObjectProvider valOP = ec.findObjectProvider(oldValue);
valOP.flush();
}
}
}
return (V) oldValue;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class FKMapStore method removeValue.
/**
* Utility to remove a value from the Map.
* @param op ObjectProvider for the map.
* @param key Key of the object
* @param oldValue Value to remove
*/
private void removeValue(ObjectProvider op, Object key, Object oldValue) {
ExecutionContext ec = op.getExecutionContext();
// Null out the key and owner fields if they are nullable
if (keyMapping.isNullable()) {
ObjectProvider vsm = ec.findObjectProvider(oldValue);
// Null the key field
vsm.replaceFieldMakeDirty(keyFieldNumber, null);
if (ec.getManageRelations()) {
ec.getRelationshipManager(vsm).relationChange(keyFieldNumber, key, null);
}
// Null the owner field
if (ownerFieldNumber >= 0) {
Object oldOwner = vsm.provideField(ownerFieldNumber);
vsm.replaceFieldMakeDirty(ownerFieldNumber, null);
if (ec.getManageRelations()) {
ec.getRelationshipManager(vsm).relationChange(ownerFieldNumber, oldOwner, null);
}
} else {
updateValueFk(op, oldValue, null);
}
} else // otherwise just delete the item
{
ec.deleteObjectInternal(oldValue);
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class FKMapStore method put.
/**
* Method to put an item in the Map.
* @param op ObjectProvider for the map.
* @param newKey The key to store the value against
* @param newValue The value to store.
* @return The value stored.
*/
public V put(final ObjectProvider op, final K newKey, V newValue) {
ExecutionContext ec = op.getExecutionContext();
if (keyFieldNumber >= 0) {
validateKeyForWriting(op, newKey);
validateValueType(ec.getClassLoaderResolver(), newValue);
} else {
validateKeyType(ec.getClassLoaderResolver(), newKey);
validateValueForWriting(op, newValue);
}
// Check if there is an existing value for this key
V oldValue = get(op, newKey);
if (oldValue != newValue) {
if (valueCmd != null) {
if (oldValue != null && !oldValue.equals(newValue)) {
// Key is stored in the value and the value has changed so remove the old value
removeValue(op, newKey, oldValue);
}
final Object newOwner = op.getObject();
if (ec.getApiAdapter().isPersistent(newValue)) {
/*
* The new value is already persistent.
*
* "Put" the new value in the map by updating its owner and key
* fields to the appropriate values. This is done with the same
* methods the PC itself would use if the application code
* modified the fields. It should result in no actual database
* activity if the fields were already set to the right values.
*/
if (ec != ec.getApiAdapter().getExecutionContext(newValue)) {
throw new NucleusUserException(Localiser.msg("RDBMS.SCO.Map.WriteValueInvalidWithDifferentPM"), ec.getApiAdapter().getIdForObject(newValue));
}
ObjectProvider vsm = ec.findObjectProvider(newValue);
// Ensure the current owner field is loaded, and replace with new value
if (ownerFieldNumber >= 0) {
vsm.isLoaded(ownerFieldNumber);
Object oldOwner = vsm.provideField(ownerFieldNumber);
vsm.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
if (ec.getManageRelations()) {
ec.getRelationshipManager(vsm).relationChange(ownerFieldNumber, oldOwner, newOwner);
}
} else {
updateValueFk(op, newValue, newOwner);
}
// Ensure the current key field is loaded, and replace with new value
vsm.isLoaded(keyFieldNumber);
Object oldKey = vsm.provideField(keyFieldNumber);
vsm.replaceFieldMakeDirty(keyFieldNumber, newKey);
if (ec.getManageRelations()) {
ec.getRelationshipManager(vsm).relationChange(keyFieldNumber, oldKey, newKey);
}
} else {
/*
* The new value is not yet persistent.
*
* Update its owner and key fields to the appropriate values and
* *then* make it persistent. Making the changes before DB
* insertion avoids an unnecessary UPDATE allows the owner
* and/or key fields to be non-nullable.
*/
ec.persistObjectInternal(newValue, new FieldValues() {
public void fetchFields(ObjectProvider vsm) {
if (ownerFieldNumber >= 0) {
vsm.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
}
vsm.replaceFieldMakeDirty(keyFieldNumber, newKey);
JavaTypeMapping externalFKMapping = valueTable.getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK);
if (externalFKMapping != null) {
// Set the owner in the value object where appropriate
vsm.setAssociatedValue(externalFKMapping, op.getObject());
}
}
public void fetchNonLoadedFields(ObjectProvider op) {
}
public FetchPlan getFetchPlanForLoading() {
return null;
}
}, ObjectProvider.PC);
}
} else {
// Value is stored in the key
final Object newOwner = op.getObject();
if (ec.getApiAdapter().isPersistent(newKey)) {
/*
* The new key is already persistent.
*
* "Put" the new key in the map by updating its owner and value
* fields to the appropriate values. This is done with the same
* methods the PC itself would use if the application code
* modified the fields. It should result in no actual database
* activity if the fields were already set to the right values.
*/
if (ec != ec.getApiAdapter().getExecutionContext(newKey)) {
throw new NucleusUserException(Localiser.msg("056060"), ec.getApiAdapter().getIdForObject(newKey));
}
ObjectProvider valOP = ec.findObjectProvider(newKey);
// Ensure the current owner field is loaded, and replace with new key
if (ownerFieldNumber >= 0) {
valOP.isLoaded(ownerFieldNumber);
Object oldOwner = valOP.provideField(ownerFieldNumber);
valOP.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
if (ec.getManageRelations()) {
ec.getRelationshipManager(valOP).relationChange(ownerFieldNumber, oldOwner, newOwner);
}
} else {
updateKeyFk(op, newKey, newOwner);
}
// Ensure the current value field is loaded, and replace with new value
valOP.isLoaded(valueFieldNumber);
// TODO Should we update the local variable ?
oldValue = (V) valOP.provideField(valueFieldNumber);
valOP.replaceFieldMakeDirty(valueFieldNumber, newValue);
if (ec.getManageRelations()) {
ec.getRelationshipManager(valOP).relationChange(valueFieldNumber, oldValue, newValue);
}
} else {
/*
* The new key is not yet persistent.
*
* Update its owner and key fields to the appropriate values and
* *then* make it persistent. Making the changes before DB
* insertion avoids an unnecessary UPDATE allows the owner
* and/or key fields to be non-nullable.
*/
final Object newValueObj = newValue;
ec.persistObjectInternal(newKey, new FieldValues() {
public void fetchFields(ObjectProvider vsm) {
if (ownerFieldNumber >= 0) {
vsm.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
}
vsm.replaceFieldMakeDirty(valueFieldNumber, newValueObj);
JavaTypeMapping externalFKMapping = valueTable.getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK);
if (externalFKMapping != null) {
// Set the owner in the value object where appropriate
vsm.setAssociatedValue(externalFKMapping, op.getObject());
}
}
public void fetchNonLoadedFields(ObjectProvider op) {
}
public FetchPlan getFetchPlanForLoading() {
return null;
}
}, ObjectProvider.PC);
/*if (ownerFieldNumber < 0)
{
// TODO Think about removing this since we set the associated owner here
updateKeyFk(sm, newKey, newOwner);
}*/
}
}
}
// TODO Cater for key being PC and having delete-dependent
if (ownerMemberMetaData.getMap().isDependentValue() && oldValue != null) {
// Delete the old value if it is no longer contained and is dependent
if (!containsValue(op, oldValue)) {
ec.deleteObjectInternal(oldValue);
}
}
return oldValue;
}
Aggregations