/** INTERNAL: Get a value from the object and set that in the respective field of the row. */ @Override public Object valueFromObject(Object object, DatabaseField field, AbstractSession session) { // First check if the value can be obtained from the value holder's row. AbstractRecord referenceRow = getIndirectionPolicy().extractReferenceRow(getAttributeValueFromObject(object)); if (referenceRow != null) { Object value = referenceRow.get(field); // Must ensure the classification to get a cache hit. try { value = session.getDatasourcePlatform().convertObject(value, getFieldClassification(field)); } catch (ConversionException e) { throw ConversionException.couldNotBeConverted(this, getDescriptor(), e); } return value; } // 2.5.1.6 PWK. added to support batch reading on variable one to ones Object referenceObject = getRealAttributeValueFromObject(object, session); String queryKeyName = (String) getSourceToTargetQueryKeyNames().get(field); ClassDescriptor objectDescriptor = session.getDescriptor(referenceObject.getClass()); DatabaseField targetField = objectDescriptor.getObjectBuilder().getTargetFieldForQueryKeyName(queryKeyName); if (targetField == null) { return null; } return objectDescriptor .getObjectBuilder() .extractValueFromObjectForField(referenceObject, targetField, session); }
/** * INTERNAL: Compare the references of the two objects are the same, not the objects themselves. * Used for independent relationships. This is used for testing and validation purposes. * * <p>Must get separate fields for the objects because we may be adding a different class to the * attribute because of the interface */ @Override protected boolean compareObjectsWithoutPrivateOwned( Object firstObject, Object secondObject, AbstractSession session) { Object firstPrivateObject = getRealAttributeValueFromObject(firstObject, session); Object secondPrivateObject = getRealAttributeValueFromObject(secondObject, session); if ((firstPrivateObject == null) && (secondPrivateObject == null)) { return true; } if ((firstPrivateObject == null) || (secondPrivateObject == null)) { return false; } if (firstPrivateObject.getClass() != secondPrivateObject.getClass()) { return false; } Iterator targetKeys = getSourceToTargetQueryKeyNames().values().iterator(); ClassDescriptor descriptor = session.getDescriptor(firstPrivateObject.getClass()); ClassDescriptor descriptor2 = session.getDescriptor(secondPrivateObject.getClass()); while (targetKeys.hasNext()) { String queryKey = (String) targetKeys.next(); DatabaseField field = descriptor.getObjectBuilder().getFieldForQueryKeyName(queryKey); Object firstObjectField = descriptor .getObjectBuilder() .extractValueFromObjectForField(firstPrivateObject, field, session); DatabaseField field2 = descriptor2.getObjectBuilder().getFieldForQueryKeyName(queryKey); Object secondObjectField = descriptor2 .getObjectBuilder() .extractValueFromObjectForField(secondPrivateObject, field2, session); if (!((firstObjectField == null) && (secondObjectField == null))) { if ((firstObjectField == null) || (secondObjectField == null)) { return false; } if (!firstObjectField.equals(secondObjectField)) { return false; } } } return true; }
/** INTERNAL: Initialize the mapping. */ public void initialize(AbstractSession session) throws DescriptorException { setReferenceDescriptor(session.getDescriptor(getReferenceClass())); if (referenceDescriptor == null) { throw DescriptorException.descriptorIsMissing(getReferenceClass().getName(), this); } // For bug 2730536 convert the field to be an ObjectRelationalDatabaseField. ObjectRelationalDatabaseField field = (ObjectRelationalDatabaseField) getField(); field.setSqlType(java.sql.Types.REF); if (referenceDescriptor instanceof ObjectRelationalDataTypeDescriptor) { field.setSqlTypeName( ((ObjectRelationalDataTypeDescriptor) referenceDescriptor).getStructureName()); } setField(getDescriptor().buildField(getField())); setFields(collectFields()); // Ref mapping requires native connection in WLS as the Ref is wrapped. getDescriptor().setIsNativeConnectionRequired(true); }
/** * INTERNAL: Get a value from the object and set that in the respective field of the row. If the * mapping id target foreign key, you must only write the type into the roe, the rest will be * updated when the object itself is written */ @Override public void writeFromObjectIntoRowWithChangeRecord( ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) { if (isReadOnly()) { return; } ObjectChangeSet changeSet = (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue(); if (changeSet == null) { writeFromNullObjectIntoRow(record); } else { Object referenceObject = changeSet.getUnitOfWorkClone(); if (isForeignKeyRelationship()) { Enumeration sourceFields = getForeignKeyFields().elements(); ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass()); while (sourceFields.hasMoreElements()) { DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement(); String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey); DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey); if (targetKeyField == null) { throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly( this, descriptor, targetQueryKey); } Object referenceValue = descriptor .getObjectBuilder() .extractValueFromObjectForField(referenceObject, targetKeyField, session); record.put(sourceKey, referenceValue); } } if (getTypeField() != null) { record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass())); } } }
/** * INTERNAL: Return a descriptor for the target of this mapping For normal * ObjectReferenceMappings, we return the reference descriptor. For a VariableOneToOneMapping, the * reference descriptor is often a descriptor for an interface and does not contain adequate * information. As a result, we look up the descriptor for the specific class we are looking for * Bug 2612571 */ @Override public ClassDescriptor getDescriptorForTarget(Object targetObject, AbstractSession session) { return session.getDescriptor(targetObject); }