use of org.datanucleus.metadata.RelationType in project datanucleus-rdbms by datanucleus.
the class ParameterSetter method storeObjectField.
public void storeObjectField(int fieldNumber, Object value) {
StatementMappingIndex mapIdx = stmtMappings.getMappingForMemberPosition(fieldNumber);
if (value == null && mapIdx.getMapping().getMemberMetaData().getNullValue() == NullValue.EXCEPTION) {
throw new NucleusUserException(Localiser.msg("052400", mapIdx.getMapping().getMemberMetaData().getFullFieldName()));
}
try {
JavaTypeMapping mapping = mapIdx.getMapping();
boolean provideOwner = false;
if (mapping instanceof EmbeddedPCMapping || mapping instanceof SerialisedPCMapping || mapping instanceof SerialisedReferenceMapping || mapping instanceof PersistableMapping || mapping instanceof InterfaceMapping) {
// Pass in the owner ObjectProvider/field for any mappings that have relations
provideOwner = true;
}
if (mapIdx.getNumberOfParameterOccurrences() > 0) {
for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
// Set this value for all occurrences of this parameter
if (provideOwner) {
mapping.setObject(ec, statement, mapIdx.getParameterPositionsForOccurrence(i), value, op, fieldNumber);
} else {
mapping.setObject(ec, statement, mapIdx.getParameterPositionsForOccurrence(i), value);
}
}
} else {
// Important : call setObject even if the paramIndices is null (reachability)
if (provideOwner) {
mapping.setObject(ec, statement, null, value, op, fieldNumber);
} else {
mapping.setObject(ec, statement, null, value);
}
}
AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
if (op.getClassMetaData().getSCOMutableMemberFlags()[fieldNumber]) {
SCOUtils.wrapSCOField(op, fieldNumber, value, true);
} else if (RelationType.isRelationSingleValued(relationType) && (mmd.getEmbeddedMetaData() != null && mmd.getEmbeddedMetaData().getOwnerMember() != null)) {
// Embedded PC, so make sure the field is wrapped where appropriate TODO This should be part of ManagedRelationships
op.updateOwnerFieldInEmbeddedField(fieldNumber, value);
}
} catch (NotYetFlushedException e) {
if (op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber).getNullValue() == NullValue.EXCEPTION) {
throw e;
}
op.updateFieldAfterInsert(e.getPersistable(), fieldNumber);
}
}
use of org.datanucleus.metadata.RelationType in project datanucleus-rdbms by datanucleus.
the class ResultSetGetter method fetchObjectField.
public Object fetchObjectField(int fieldNumber) {
StatementMappingIndex mapIdx = resultMappings.getMappingForMemberPosition(fieldNumber);
JavaTypeMapping mapping = mapIdx.getMapping();
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
Object value;
if (mapping instanceof EmbeddedPCMapping || mapping instanceof SerialisedPCMapping || mapping instanceof SerialisedReferenceMapping) {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions(), op, fieldNumber);
} else {
if (mmd.isSingleCollection()) {
StatementClassMapping relationMappings = resultMappings.getMappingDefinitionForMemberPosition(fieldNumber);
if (relationMappings != null) {
Class type = ec.getClassLoaderResolver().classForName(mmd.getCollection().getElementType());
value = processSubObjectFields(mapping, type, relationMappings);
ElementContainerHandler containerHandler = ec.getTypeManager().getContainerHandler(mmd.getType());
value = containerHandler.newContainer(mmd, value);
} else {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
}
} else if (RelationType.isRelationSingleValued(relationType)) {
// Process fields of sub-object if available in this result set
StatementClassMapping relationMappings = resultMappings.getMappingDefinitionForMemberPosition(fieldNumber);
if (relationMappings != null) {
value = processSubObjectFields(mapping, mmd.getType(), relationMappings);
} else {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
}
} else {
value = mapping.getObject(ec, rs, mapIdx.getColumnPositions());
}
}
if (op != null) {
if (cmd.getSCOMutableMemberFlags()[fieldNumber]) {
// Wrap any SCO mutable fields
return SCOUtils.wrapSCOField(op, fieldNumber, value, false);
} else if (RelationType.isRelationSingleValued(relationType) && (mmd.getEmbeddedMetaData() != null && mmd.getEmbeddedMetaData().getOwnerMember() != null)) {
// Embedded PC, so make sure the field is wrapped where appropriate TODO This should be part of ManagedRelationships
op.updateOwnerFieldInEmbeddedField(fieldNumber, value);
return value;
}
}
return value;
}
use of org.datanucleus.metadata.RelationType in project datanucleus-core by datanucleus.
the class RelationshipManagerImpl method relationChange.
/* (non-Javadoc)
* @see org.datanucleus.state.RelationshipManager#relationChange(int, java.lang.Object, java.lang.Object)
*/
public void relationChange(int fieldNumber, Object oldValue, Object newValue) {
if (ec.isManagingRelations()) {
return;
}
Integer fieldKey = Integer.valueOf(fieldNumber);
List<RelationChange> changes = fieldChanges.get(fieldKey);
if (changes == null) {
changes = new ArrayList<RelationChange>();
fieldChanges.put(fieldKey, changes);
}
AbstractMemberMetaData mmd = ownerOP.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
if (relationType == RelationType.ONE_TO_ONE_BI || relationType == RelationType.MANY_TO_ONE_BI) {
// TODO If this field is changed multiple times, we don't currently handle it e.g "myObj.setX(null);" followed by "myObj.setX(newX);"
if (changes.isEmpty()) {
changes.add(new RelationChange(ChangeType.CHANGE_OBJECT, newValue, oldValue));
}
return;
}
if (relationType == RelationType.ONE_TO_MANY_BI || relationType == RelationType.MANY_TO_MANY_BI) {
// TODO What about Map?
if (mmd.hasCollection()) {
Collection oldColl = (Collection) oldValue;
Collection newColl = (Collection) newValue;
if (oldColl == null) {
if (newColl != null) {
// Add all elements
for (Object newElem : newColl) {
changes.add(new RelationChange(ChangeType.ADD_OBJECT, newElem));
}
}
} else {
if (newColl == null) {
AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver())[0];
for (Object element : oldColl) {
if (ownerOP.getLifecycleState().isDeleted) {
// Deleting the owner, so register the element to reset its owner
ec.removeObjectFromLevel2Cache(ec.getApiAdapter().getIdForObject(element));
ObjectProvider elementOP = ec.findObjectProvider(element);
if (relationType == RelationType.ONE_TO_MANY_BI) {
// TODO This needs marking as a secondary change. i.e we dont want follow on checks, just null out the relation during process()
ec.getRelationshipManager(elementOP).relationChange(relatedMmd.getAbsoluteFieldNumber(), ownerOP.getObject(), null);
} else if (relationType == RelationType.MANY_TO_MANY_BI) {
// TODO This needs marking as a secondary change. i.e we don't want follow on checks, just remove the element from the relation during process()
ec.getRelationshipManager(elementOP).relationRemove(relatedMmd.getAbsoluteFieldNumber(), ownerOP.getObject());
}
} else {
// Remove the element
changes.add(new RelationChange(ChangeType.REMOVE_OBJECT, element));
}
}
} else {
// Remove some and add some
for (Object newElem : newColl) {
boolean alreadyExists = false;
for (Object oldElem : oldColl) {
if (newElem == oldElem) {
alreadyExists = true;
break;
}
}
if (!alreadyExists) {
ObjectProvider elemOP = ec.findObjectProvider(newElem);
if (elemOP != null) {
AbstractMemberMetaData elemMmd = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver())[0];
Object oldOwner = elemOP.provideField(elemMmd.getAbsoluteFieldNumber());
if (!elemOP.isFieldLoaded(elemMmd.getAbsoluteFieldNumber())) {
elemOP.loadField(elemMmd.getAbsoluteFieldNumber());
}
if (oldOwner != null) {
// Remove from old owner collection
ObjectProvider oldOwnerOP = ec.findObjectProvider(oldOwner);
if (oldOwnerOP != null) {
// TODO This needs marking as a secondary change. i.e we dont want follow on checks, just remove the element from the relation during process()
ec.getRelationshipManager(oldOwnerOP).relationRemove(fieldNumber, newElem);
}
}
}
relationAdd(fieldNumber, newElem);
}
}
for (Object oldElem : oldColl) {
boolean stillExists = false;
for (Object newElem : newColl) {
if (oldElem == newElem) {
stillExists = true;
break;
}
}
if (!stillExists) {
relationRemove(fieldNumber, oldElem);
}
}
}
}
}
}
}
use of org.datanucleus.metadata.RelationType in project datanucleus-core by datanucleus.
the class RelationshipManagerImpl method relationAdd.
/* (non-Javadoc)
* @see org.datanucleus.state.RelationshipManager#relationAdd(int, java.lang.Object)
*/
public void relationAdd(int fieldNumber, Object val) {
if (ec.isManagingRelations()) {
return;
}
AbstractMemberMetaData mmd = ownerOP.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
if (relationType != RelationType.ONE_TO_MANY_BI && relationType != RelationType.MANY_TO_MANY_BI) {
return;
}
ObjectProvider elemOP = ec.findObjectProvider(val);
if (elemOP != null) {
AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver())[0];
if (elemOP.isFieldLoaded(relatedMmd.getAbsoluteFieldNumber())) {
Object currentOwnerId = ec.getApiAdapter().getIdForObject(elemOP.provideField(relatedMmd.getAbsoluteFieldNumber()));
ec.removeObjectFromLevel2Cache(currentOwnerId);
}
}
Integer fieldKey = Integer.valueOf(fieldNumber);
List<RelationChange> changeList = fieldChanges.get(fieldKey);
if (changeList == null) {
changeList = new ArrayList();
fieldChanges.put(fieldKey, changeList);
}
ec.removeObjectFromLevel2Cache(ec.getApiAdapter().getIdForObject(val));
changeList.add(new RelationChange(ChangeType.ADD_OBJECT, val));
}
use of org.datanucleus.metadata.RelationType in project datanucleus-core by datanucleus.
the class StateManagerImpl method refreshFieldsInFetchPlan.
/**
* Refreshes from the database all fields in fetch plan.
* Called by life-cycle transitions when the object undergoes a "transitionRefresh".
*/
public void refreshFieldsInFetchPlan() {
int[] fieldNumbers = myFP.getMemberNumbers();
if (fieldNumbers != null && fieldNumbers.length > 0) {
clearDirtyFlags(fieldNumbers);
ClassUtils.clearFlags(loadedFields, fieldNumbers);
// Can't refresh PK fields!
markPKFieldsAsLoaded();
boolean callPostLoad = myFP.isToCallPostLoadFetchPlan(this.loadedFields);
// Refresh the fetch plan fields in this object
// Make sure that the version is reset upon fetch
setTransactionalVersion(null);
loadFieldsFromDatastore(fieldNumbers);
if (cmd.hasRelations(myEC.getClassLoaderResolver())) {
// Check for cascade refreshes to related objects
for (int i = 0; i < fieldNumbers.length; i++) {
AbstractMemberMetaData fmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumbers[i]);
RelationType relationType = fmd.getRelationType(myEC.getClassLoaderResolver());
if (relationType != RelationType.NONE && fmd.isCascadeRefresh()) {
// Need to refresh the related field object(s)
Object value = provideField(fieldNumbers[i]);
if (value != null) {
if (fmd.hasContainer()) {
// TODO This should replace the SCO wrapper with a new one, or reload the wrapper
ApiAdapter api = getExecutionContext().getApiAdapter();
ContainerHandler containerHandler = myEC.getTypeManager().getContainerHandler(fmd.getType());
for (Object object : containerHandler.getAdapter(value)) {
if (api.isPersistable(object)) {
getExecutionContext().refreshObject(object);
}
}
} else if (value instanceof Persistable) {
// Refresh any PC fields
myEC.refreshObject(value);
}
}
}
}
}
updateLevel2CacheForFields(fieldNumbers);
if (callPostLoad) {
postLoad();
}
getCallbackHandler().postRefresh(myPC);
}
}
Aggregations