/** * INTERNAL: * Initialize the mapping. */ public void initialize(AbstractSession session) throws DescriptorException { super.initialize(session); // Must set table of foreign keys. for (Enumeration foreignKeysEnum = getForeignKeyFields().elements(); foreignKeysEnum.hasMoreElements();) { DatabaseField foreignKeyField = (DatabaseField)foreignKeysEnum.nextElement(); getDescriptor().buildField(foreignKeyField); } // If only a selection criteria is specified then the foreign keys do not have to be initialized. if (!(getTargetToSourceKeyFields().isEmpty() && getSourceToTargetKeyFields().isEmpty())) { if (getTargetToSourceKeyFields().isEmpty() || getSourceToTargetKeyFields().isEmpty()) { initializeForeignKeysWithDefaults(session); } else { initializeForeignKeys(session); } } if (shouldInitializeSelectionCriteria()) { initializeSelectionCriteria(session); } else { setShouldVerifyDelete(false); } setFields(collectFields()); }
if (isReadOnly() || (!isForeignKeyRelationship())) { return; AbstractRecord referenceRow = getIndirectionPolicy().extractReferenceRow(getAttributeValueFromObject(object)); if (referenceRow == null) { Object referenceObject = getRealAttributeValueFromObject(object, session); for (Enumeration fieldsEnum = getForeignKeyFields().elements(); fieldsEnum.hasMoreElements();) { DatabaseField sourceKey = (DatabaseField)fieldsEnum.nextElement(); DatabaseField targetKey = (DatabaseField)getSourceToTargetKeyFields().get(sourceKey); referenceValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(referenceObject, targetKey, session); for (Enumeration fieldsEnum = getForeignKeyFields().elements(); fieldsEnum.hasMoreElements();) { DatabaseField sourceKey = (DatabaseField)fieldsEnum.nextElement();
/** * INTERNAL: * Get a value from the object and set that in the respective field of the row. */ 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; } Object referenceObject = getRealAttributeValueFromObject(object, session); if (referenceObject == null) { return null; } DatabaseField targetField = (DatabaseField)getSourceToTargetKeyFields().get(field); return getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(referenceObject, targetField, session); }
/** * Return the appropriate hashtable that maps the "foreign keys" * to the "primary keys". */ protected Map getForeignKeysToPrimaryKeys() { if (this.isForeignKeyRelationship()) { return this.getSourceToTargetKeyFields(); } else { return this.getTargetToSourceKeyFields(); } }
/** * Return the descriptor for whichever side of the * relation has the "primary key". */ protected ClassDescriptor getPrimaryKeyDescriptor() { if (this.isForeignKeyRelationship()) { return this.getReferenceDescriptor(); } else { return this.getDescriptor(); } }
/** * INTERNAL: * Rehash any hashtables based on fields. * This is used to clone descriptors for aggregates, which hammer field names, * it is probably better not to hammer the field name and this should be refactored. */ public void rehashFieldDependancies(AbstractSession session) { setSourceToTargetKeyFields(Helper.rehashMap(getSourceToTargetKeyFields())); }
/** * INTERNAL: * Initialize a OneToOneMapping. */ protected OneToOneMapping initOneToOneMapping() { OneToOneMapping mapping = new OneToOneMapping(); mapping.setIsReadOnly(false); mapping.setIsPrivateOwned(false); mapping.setIsOptional(isOptional()); mapping.setAttributeName(getAttributeName()); mapping.setReferenceClassName(getReferenceClassName()); // If the global weave for value holders is true, the use the value // from usesIndirection. Otherwise, force it to false. boolean usesIndirection = (m_project.enableLazyForOneToOne()) ? usesIndirection() : false; if (usesIndirection && m_descriptor.usesPropertyAccess()) { mapping.setIndirectionPolicy(new WeavedObjectBasicIndirectionPolicy(getSetMethodName())); } else { mapping.setUsesIndirection(usesIndirection); } // Set the getter and setter methods if access is PROPERTY. setAccessorMethods(mapping); // Process the cascade types. processCascadeTypes(mapping); return mapping; }
/** * INTERNAL: * The foreign keys primary keys are stored as database fields in the hashtable. */ protected void initializeForeignKeys(AbstractSession session) { Iterator sourceEnum = getSourceToTargetKeyFields().keySet().iterator(); Iterator targetEnum = getTargetToSourceKeyFields().keySet().iterator(); while (sourceEnum.hasNext()) { DatabaseField sourceField = (DatabaseField)sourceEnum.next(); DatabaseField targetField = (DatabaseField)targetEnum.next(); getDescriptor().buildField(sourceField); getReferenceDescriptor().buildField(targetField); } }
clone.setForeignKeyFields(oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(getForeignKeyFields().size())); clone.setSourceToTargetKeyFields(new HashMap(getSourceToTargetKeyFields().size())); clone.setTargetToSourceKeyFields(new HashMap(getTargetToSourceKeyFields().size())); Hashtable setOfFields = new Hashtable(getTargetToSourceKeyFields().size()); for (Enumeration enumtr = getForeignKeyFields().elements(); enumtr.hasMoreElements();) { DatabaseField field = (DatabaseField)enumtr.nextElement(); DatabaseField fieldClone = (DatabaseField)field.clone(); setOfFields.put(field, fieldClone); clone.getForeignKeyFields().addElement(fieldClone); for (Iterator sourceEnum = getSourceToTargetKeyFields().keySet().iterator(); sourceEnum.hasNext();) { DatabaseField sourceField = (DatabaseField)sourceEnum.next(); DatabaseField targetField = (DatabaseField)getSourceToTargetKeyFields().get(sourceField); setOfFields.put(sourceField, sourceClone); clone.getSourceToTargetKeyFields().put(sourceClone, targetClone); for (Iterator targetEnum = getTargetToSourceKeyFields().keySet().iterator(); targetEnum.hasNext();) { DatabaseField targetField = (DatabaseField)targetEnum.next(); DatabaseField sourceField = (DatabaseField)getTargetToSourceKeyFields().get(targetField); setOfFields.put(sourceField, sourceClone); clone.getTargetToSourceKeyFields().put(targetClone, sourceClone);
/** * INTERNAL: * Set a collection of the source to target field associations. */ public void setSourceToTargetKeyFieldAssociations(Vector sourceToTargetKeyFieldAssociations) { setSourceToTargetKeyFields(new HashMap(sourceToTargetKeyFieldAssociations.size() + 1)); setTargetToSourceKeyFields(new HashMap(sourceToTargetKeyFieldAssociations.size() + 1)); for (Enumeration associationsEnum = sourceToTargetKeyFieldAssociations.elements(); associationsEnum.hasMoreElements();) { Association association = (Association)associationsEnum.nextElement(); DatabaseField sourceField = new DatabaseField((String)association.getKey()); DatabaseField targetField = new DatabaseField((String)association.getValue()); getSourceToTargetKeyFields().put(sourceField, targetField); getTargetToSourceKeyFields().put(targetField, sourceField); } }
/** * PUBLIC: * Define the foreign key relationship in the 1-1 mapping. * This method is used for composite foreign key relationships, * that is the source object's table has multiple foreign key fields to * the target object's primary key fields. * Both the source foreign key field and the target foreign key field must * be specified. * When a foreign key is specified TopLink will automatically populate the * value for that field from the target object when the object is written to * the database. If the foreign key is also mapped through a direct-to-field * then the direct-to-field must be set read-only. */ public void addForeignKeyField(DatabaseField sourceForeignKeyField, DatabaseField targetPrimaryKeyField) { setIsForeignKeyRelationship(true); getForeignKeyFields().addElement(sourceForeignKeyField); getSourceToTargetKeyFields().put(sourceForeignKeyField, targetPrimaryKeyField); getTargetToSourceKeyFields().put(targetPrimaryKeyField, sourceForeignKeyField); }
/** * INTERNAL: * Selection criteria is created with source foreign keys and target keys. */ protected void initializePrivateOwnedCriteria() { if (!isForeignKeyRelationship()) { setPrivateOwnedCriteria(getSelectionCriteria()); } else { Expression pkCriteria = getDescriptor().getObjectBuilder().getPrimaryKeyExpression(); ExpressionBuilder builder = new ExpressionBuilder(); Expression backRef = builder.getManualQueryKey(getAttributeName() + "-back-ref", getDescriptor()); Expression newPKCriteria = pkCriteria.rebuildOn(backRef); Expression twistedSelection = backRef.twist(getSelectionCriteria(), builder); if (getDescriptor().getQueryManager().getAdditionalJoinExpression() != null) { // We don't have to twist the additional join because it's all against the same node, which is our base // but we do have to rebuild it onto the manual query key Expression rebuiltAdditional = getDescriptor().getQueryManager().getAdditionalJoinExpression().rebuildOn(backRef); if (twistedSelection == null) { twistedSelection = rebuiltAdditional; } else { twistedSelection = twistedSelection.and(rebuiltAdditional); } } setPrivateOwnedCriteria(newPKCriteria.and(twistedSelection)); } }
/** * INTERNAL: * Builds a shallow original object. Only direct attributes and primary * keys are populated. In this way the minimum original required for * instantiating a working copy clone can be built without placing it in * the shared cache (no concern over cycles). */ public void buildShallowOriginalFromRow(AbstractRecord databaseRow, Object original, ObjectBuildingQuery query, AbstractSession executionSession) { // Now we are only building this original so we can extract the primary // key out of it. If the primary key is stored accross a 1-1 a value // holder needs to be built/triggered to get at it. // In this case recursively build the shallow original accross the 1-1. // We only need the primary key for that object, and we know // what that primary key is: it is the foreign key in our row. ClassDescriptor descriptor = getReferenceDescriptor(); AbstractRecord targetRow = new DatabaseRecord(); for (Iterator keys = getSourceToTargetKeyFields().keySet().iterator(); keys.hasNext();) { DatabaseField foreignKey = (DatabaseField)keys.next(); DatabaseField targetKey = (DatabaseField)getSourceToTargetKeyFields().get(foreignKey); targetRow.put(targetKey, databaseRow.get(foreignKey)); } Object targetObject = descriptor.getObjectBuilder().buildNewInstance(); descriptor.getObjectBuilder().buildAttributesIntoShallowObject(targetObject, databaseRow, query); targetObject = getIndirectionPolicy().valueFromRow(targetObject); setAttributeValueInObject(original, targetObject); }
if (!isForeignKeyRelationship()) { throw QueryException.cannotCompareTargetForeignKeysToNull(base, value, this); for (Iterator sourceFieldsEnum = getSourceToTargetKeyFields().keySet().iterator(); sourceFieldsEnum.hasNext();) { DatabaseField field = (DatabaseField)sourceFieldsEnum.next(); if (!getReferenceDescriptor().getJavaClass().isInstance(value)) { throw QueryException.incorrectClassForObjectComparison(base, value, this); Enumeration keyEnum = extractKeyFromReferenceObject(value, session).elements(); for (Iterator sourceFieldsEnum = getSourceToTargetKeyFields().keySet().iterator(); sourceFieldsEnum.hasNext();) { DatabaseField field = (DatabaseField)sourceFieldsEnum.next();
/** * INTERNAL: * Extract the key value from the reference object. */ protected Vector extractKeyFromReferenceObject(Object object, AbstractSession session) { Vector key = new Vector(); for (Iterator fieldEnum = getSourceToTargetKeyFields().values().iterator(); fieldEnum.hasNext();) { DatabaseField field = (DatabaseField)fieldEnum.next(); if (object == null) { key.addElement(null); } else { key.addElement(getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, field, session)); } } return key; }
/** * INTERNAL: * Return a collection of the source to target field value associations. */ public Vector getSourceToTargetKeyFieldAssociations() { Vector associations = new Vector(getSourceToTargetKeyFields().size()); Iterator sourceFieldEnum = getSourceToTargetKeyFields().keySet().iterator(); Iterator targetFieldEnum = getSourceToTargetKeyFields().values().iterator(); while (sourceFieldEnum.hasNext()) { Object fieldValue = ((DatabaseField)sourceFieldEnum.next()).getQualifiedName(); Object attributeValue = ((DatabaseField)targetFieldEnum.next()).getQualifiedName(); associations.addElement(new Association(fieldValue, attributeValue)); } return associations; }
/** * PUBLIC: * Define the foreign key relationship in the 1-1 mapping. * This method is used for singleton foreign key relationships only, * that is the source object's table has a foreign key field to * the target object's primary key field. * Only the source foreign key field name is specified. * When a foreign key is specified TopLink will automatically populate the value * for that field from the target object when the object is written to the database. * If the foreign key is also mapped through a direct-to-field then the direct-to-field must * be set read-only. */ public void setForeignKeyFieldName(String sourceForeignKeyFieldName) { DatabaseField sourceField = new DatabaseField(sourceForeignKeyFieldName); setIsForeignKeyRelationship(true); getForeignKeyFields().addElement(sourceField); getSourceToTargetKeyFields().put(sourceField, new DatabaseField()); }
/** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Write the foreign key values from the attribute to the row. */ public void writeFromAttributeIntoRow(Object attribute, AbstractRecord row, AbstractSession session) { for (Enumeration fieldsEnum = getForeignKeyFields().elements(); fieldsEnum.hasMoreElements();) { DatabaseField sourceKey = (DatabaseField) fieldsEnum.nextElement(); DatabaseField targetKey = (DatabaseField) getSourceToTargetKeyFields().get(sourceKey); Object referenceValue = null; // If privately owned part is null then method cannot be invoked. if (attribute != null) { referenceValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(attribute, targetKey, session); } row.add(sourceKey, referenceValue); } }
/** * INTERNAL: * Selection criteria is created with source foreign keys and target keys. * This criteria is then used to read target records from the table. * * CR#3922 - This method is almost the same as buildSelectionCriteria() the difference * is that getSelectionCriteria() is called */ protected void initializeSelectionCriteria(AbstractSession session) { if (getSourceToTargetKeyFields().isEmpty()) { throw DescriptorException.noForeignKeysAreSpecified(this); } Expression criteria; Expression builder = new ExpressionBuilder(); for (Iterator entries = getSourceToTargetKeyFields().entrySet().iterator(); entries.hasNext();) { Map.Entry entry = (Map.Entry) entries.next(); DatabaseField foreignKey = (DatabaseField)entry.getKey(); DatabaseField targetKey = (DatabaseField)entry.getValue(); Expression expression = builder.getField(targetKey).equal(builder.getParameter(foreignKey)); criteria = expression.and(getSelectionCriteria()); setSelectionCriteria(criteria); } }
AbstractRecord targetRow = trimRowForJoin(row, joinManager, executionSession); if (joinManager.isAttributeJoined(getDescriptor(), getAttributeName()) && joinManager.hasOuterJoinedAttributeQuery()) { Vector key = this.referenceDescriptor.getObjectBuilder().extractPrimaryKeyFromRow(targetRow, executionSession); if (key == null) { nestedQuery = (ObjectLevelReadQuery) joinManager.getJoinedMappingQueries_().get(this); } else { nestedQuery = prepareNestedJoins(joinManager, executionSession);