/** 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: Return the value of the field from the row or a value holder on the query to obtain * the object. Check for batch + aggregation reading. */ public Object valueFromRow( AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession executionSession) throws DatabaseException { Ref ref = (Ref) row.get(getField()); if (ref == null) { return null; } Struct struct; try { ((DatabaseAccessor) executionSession.getAccessor()).incrementCallCount(executionSession); java.sql.Connection connection = ((DatabaseAccessor) executionSession.getAccessor()).getConnection(); struct = (Struct) executionSession.getPlatform().getRefValue(ref, executionSession, connection); } catch (java.sql.SQLException exception) { throw DatabaseException.sqlException(exception, executionSession, false); } AbstractRecord targetRow = ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor()) .buildRowFromStructure(struct); ((DatabaseAccessor) executionSession.getAccessor()).decrementCallCount(); return getReferenceDescriptor().getObjectBuilder().buildObject(query, targetRow, joinManager); }
/** * 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: Return the implementor for a specified type */ protected Object getImplementorForType(Object type, AbstractSession session) { if (type == null) { return getTypeIndicatorTranslation().get(Helper.getNullWrapper()); } // Must ensure the type is the same, i.e. Integer != BigDecimal. try { type = session.getDatasourcePlatform().convertObject(type, getTypeField().getType()); } catch (ConversionException e) { throw ConversionException.couldNotBeConverted(this, getDescriptor(), e); } return getTypeIndicatorTranslation().get(type); }
/** 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: */ @Override protected Object getPrimaryKeyForObject(Object object, AbstractSession session) { return session.getId(object); }
/** * 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); }