Methods Summary |
---|
public void | addTargetForeignKeyField(oracle.toplink.essentials.internal.helper.DatabaseField targetForeignKeyField, oracle.toplink.essentials.internal.helper.DatabaseField sourceKeyField)INTERNAL:
Add the associated fields to the appropriate collections.
this.getTargetForeignKeyFields().addElement(targetForeignKeyField);
this.getSourceKeyFields().addElement(sourceKeyField);
|
public void | addTargetForeignKeyFieldName(java.lang.String targetForeignKeyFieldName, java.lang.String sourceKeyFieldName)PUBLIC:
Define the target foreign key relationship in the one-to-many mapping.
This method is used for composite target foreign key relationships.
That is, the target object's table has multiple foreign key fields
that are references to
the source object's (typically primary) key fields.
Both the target foreign key field name and the corresponding
source primary key field name must be specified.
Because the target object's table must store a foreign key to the source table,
the target object must map that foreign key, this is normally done through a
one-to-one mapping back-reference. Other options include:
- use a DirectToFieldMapping and maintain the
foreign key fields directly in the target
- use a ManyToManyMapping
- use an AggregateCollectionMapping
this.addTargetForeignKeyField(new DatabaseField(targetForeignKeyFieldName), new DatabaseField(sourceKeyFieldName));
|
protected oracle.toplink.essentials.expressions.Expression | buildDefaultSelectionCriteria()The selection criteria are created with target foreign keys and source "primary" keys.
These criteria are then used to read the target records from the table.
These criteria are also used as the default "delete all" criteria.
CR#3922 - This method is almost the same as buildSelectionCriteria() the difference
is that TargetForeignKeysToSourceKeys contains more information after login then SourceKeyFields
contains before login.
Expression selectionCriteria = null;
Expression builder = new ExpressionBuilder();
for (Iterator keys = this.getTargetForeignKeysToSourceKeys().keySet().iterator();
keys.hasNext();) {
DatabaseField targetForeignKey = (DatabaseField)keys.next();
DatabaseField sourceKey = (DatabaseField)this.getTargetForeignKeysToSourceKeys().get(targetForeignKey);
Expression partialSelectionCriteria = builder.getField(targetForeignKey).equal(builder.getParameter(sourceKey));
selectionCriteria = partialSelectionCriteria.and(selectionCriteria);
}
return selectionCriteria;
|
public oracle.toplink.essentials.expressions.Expression | buildSelectionCriteria()This method would allow customers to get the potential selection criteria for a mapping
prior to initialization. This would allow them to more easily create an ammendment method
that would ammend the SQL for the join.
CR#3922 - This method is almost the same as buildDefaultSelectionCriteria() the difference
is that TargetForeignKeysToSourceKeys contains more information after login then SourceKeyFields
contains before login.
//CR3922
Expression selectionCriteria = null;
Expression builder = new ExpressionBuilder();
Enumeration sourceKeys = this.getSourceKeyFields().elements();
for (Enumeration targetForeignKeys = this.getTargetForeignKeyFields().elements();
targetForeignKeys.hasMoreElements();) {
DatabaseField targetForeignKey = (DatabaseField)targetForeignKeys.nextElement();
DatabaseField sourceKey = (DatabaseField)sourceKeys.nextElement();
Expression partialSelectionCriteria = builder.getField(targetForeignKey).equal(builder.getParameter(sourceKey));
selectionCriteria = partialSelectionCriteria.and(selectionCriteria);
}
return selectionCriteria;
|
public java.lang.Object | clone()INTERNAL:
Clone the appropriate attributes.
OneToManyMapping clone = (OneToManyMapping)super.clone();
clone.setTargetForeignKeysToSourceKeys(new HashMap(this.getTargetForeignKeysToSourceKeys()));
return clone;
|
protected void | deleteAll(oracle.toplink.essentials.queryframework.WriteObjectQuery query)Delete all the reference objects with a single query.
Object referenceObjects = null;
if(usesIndirection()) {
Object attribute = getAttributeAccessor().getAttributeValueFromObject(query.getObject());
if(attribute == null || (ClassConstants.IndirectContainer_Class.isAssignableFrom(attribute.getClass()) && !((IndirectContainer)attribute).isInstantiated())) {
// An empty Vector indicates to DeleteAllQuery that no objects should be removed from cache
referenceObjects = new Vector(0);
}
}
if(referenceObjects == null) {
referenceObjects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
}
((DeleteAllQuery)this.getDeleteAllQuery()).executeDeleteAll(query.getSession().getSessionForClass(this.getReferenceClass()), query.getTranslationRow(), this.getContainerPolicy().vectorFor(referenceObjects, query.getSession()));
|
protected void | deleteReferenceObjectsLeftOnDatabase(oracle.toplink.essentials.queryframework.WriteObjectQuery query)This method will make sure that all the records privately owned by this mapping are
actually removed. If such records are found then those are all read and removed one
by one along with their privately owned parts.
Object objects = this.readPrivateOwnedForObject(query);
// Delete all these object one by one.
ContainerPolicy cp = this.getContainerPolicy();
for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
query.getSession().deleteObject(cp.next(iter, query.getSession()));
}
|
protected java.util.Vector | extractForeignKeyFromReferenceObject(java.lang.Object object, oracle.toplink.essentials.internal.sessions.AbstractSession session)Extract the foreign key value from the reference object.
Used for batch reading. Keep the fields in the same order
as in the targetForeignKeysToSourceKeys hashtable.
Vector foreignKey = new Vector(this.getTargetForeignKeysToSourceKeys().size());
for (Iterator stream = this.getTargetForeignKeysToSourceKeys().entrySet().iterator();
stream.hasNext();) {
Map.Entry entry = (Map.Entry)stream.next();
DatabaseField targetField = (DatabaseField)entry.getKey();
DatabaseField sourceField = (DatabaseField)entry.getValue();
if (object == null) {
foreignKey.addElement(null);
} else {
Object value = this.getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, targetField, session);
//CR:somenewsgroupbug need to ensure source and target types match.
try {
value = session.getDatasourcePlatform().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(sourceField));
} catch (ConversionException e) {
throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
}
foreignKey.addElement(value);
}
}
return foreignKey;
|
protected java.util.Vector | extractKeyFromRow(oracle.toplink.essentials.internal.sessions.AbstractRecord row, oracle.toplink.essentials.internal.sessions.AbstractSession session)Extract the key field values from the specified row.
Used for batch reading. Keep the fields in the same order
as in the targetForeignKeysToSourceKeys hashtable.
Vector key = new Vector(this.getTargetForeignKeysToSourceKeys().size());
for (Iterator stream = this.getTargetForeignKeysToSourceKeys().values().iterator();
stream.hasNext();) {
DatabaseField field = (DatabaseField)stream.next();
Object value = row.get(field);
// Must ensure the classification to get a cache hit.
try {
value = session.getDatasourcePlatform().convertObject(value, getDescriptor().getObjectBuilder().getFieldClassification(field));
} catch (ConversionException e) {
throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
}
key.addElement(value);
}
return key;
|
public java.util.Vector | getSourceKeyFieldNames()PUBLIC:
Return the source key field names associated with the mapping.
These are in-order with the targetForeignKeyFieldNames.
Vector fieldNames = new Vector(getSourceKeyFields().size());
for (Enumeration fieldsEnum = getSourceKeyFields().elements();
fieldsEnum.hasMoreElements();) {
fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
}
return fieldNames;
|
public java.util.Vector | getSourceKeyFields()INTERNAL:
Return the source key fields.
return sourceKeyFields;
|
public java.util.Map | getSourceKeysToTargetForeignKeys()INTERNAL:
Return the source/target key fields.
return sourceKeysToTargetForeignKeys;
|
public java.util.Vector | getTargetForeignKeyFieldNames()INTERNAL:
Return the target foreign key field names associated with the mapping.
These are in-order with the targetForeignKeyFieldNames.
Vector fieldNames = new Vector(getTargetForeignKeyFields().size());
for (Enumeration fieldsEnum = getTargetForeignKeyFields().elements();
fieldsEnum.hasMoreElements();) {
fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
}
return fieldNames;
|
public java.util.Vector | getTargetForeignKeyFields()INTERNAL:
Return the target foreign key fields.
return targetForeignKeyFields;
|
public java.util.Map | getTargetForeignKeyToSourceKeys()INTERNAL:
Maintain for backward compatibility.
This is 'public' so StoredProcedureGenerator
does not have to use the custom query expressions.
return this.getTargetForeignKeysToSourceKeys();
|
public java.util.Map | getTargetForeignKeysToSourceKeys()INTERNAL:
Return the target/source key fields.
return targetForeignKeysToSourceKeys;
|
public boolean | hasInverseConstraintDependency()INTERNAL:
Return whether the mapping has any inverse constraint dependencies,
such as foreign keys and join tables.
return true;
|
public void | initialize(oracle.toplink.essentials.internal.sessions.AbstractSession session)INTERNAL:
Initialize the mapping.
super.initialize(session);
if (!this.isSourceKeySpecified()) {
// sourceKeyFields will be empty when #setTargetForeignKeyFieldName() is used
this.setSourceKeyFields(oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(getDescriptor().getPrimaryKeyFields()));
}
this.initializeTargetForeignKeysToSourceKeys();
if (this.shouldInitializeSelectionCriteria()) {
this.setSelectionCriteria(this.buildDefaultSelectionCriteria());
}
this.initializeDeleteAllQuery();
|
protected void | initializeDeleteAllQuery()Initialize the delete all query.
This query is used to delete the collection of objects from the
database.
((DeleteAllQuery)this.getDeleteAllQuery()).setReferenceClass(this.getReferenceClass());
if (!this.hasCustomDeleteAllQuery()) {
// the selection criteria are re-used by the delete all query
if (this.getSelectionCriteria() == null) {
this.getDeleteAllQuery().setSelectionCriteria(this.buildDefaultSelectionCriteria());
} else {
this.getDeleteAllQuery().setSelectionCriteria(this.getSelectionCriteria());
}
}
|
protected void | initializeTargetForeignKeysToSourceKeys()Verify, munge, and hash the target foreign keys and source keys.
if (this.getTargetForeignKeyFields().isEmpty()) {
if (this.shouldInitializeSelectionCriteria()) {
throw DescriptorException.noTargetForeignKeysSpecified(this);
} else {
// if they have specified selection criteria, the keys do not need to be specified
return;
}
}
if (this.getTargetForeignKeyFields().size() != this.getSourceKeyFields().size()) {
throw DescriptorException.targetForeignKeysSizeMismatch(this);
}
for (Enumeration stream = this.getTargetForeignKeyFields().elements();
stream.hasMoreElements();) {
this.getReferenceDescriptor().buildField((DatabaseField)stream.nextElement());
}
for (Enumeration keys = this.getSourceKeyFields().elements(); keys.hasMoreElements();) {
this.getDescriptor().buildField((DatabaseField)keys.nextElement());
}
Enumeration<DatabaseField> targetForeignKeys = this.getTargetForeignKeyFields().elements();
Enumeration<DatabaseField> sourceKeys = this.getSourceKeyFields().elements();
while (targetForeignKeys.hasMoreElements()) {
DatabaseField targetForeignKey = targetForeignKeys.nextElement();
DatabaseField sourcePrimaryKey = sourceKeys.nextElement();
this.getTargetForeignKeysToSourceKeys().put(targetForeignKey, sourcePrimaryKey);
this.getSourceKeysToTargetForeignKeys().put(sourcePrimaryKey, targetForeignKey);
//this.getTargetForeignKeysToSourceKeys().put(targetForeignKeys.nextElement(), sourceKeys.nextElement());
}
|
public boolean | isCascadedLockingSupported()INTERNAL
Return true if this mapping supports cascaded version optimistic locking.
return true;
|
public boolean | isJoiningSupported()INTERNAL:
Return if this mapping support joining.
return true;
|
public boolean | isOneToManyMapping()INTERNAL:
return true;
|
public boolean | isRelationalMapping()INTERNAL:
return true;
|
protected boolean | isSourceKeySpecified()Return whether the source key is specified.
It will be empty when #setTargetForeignKeyFieldName(String) is used.
return !this.getSourceKeyFields().isEmpty();
|
protected boolean | mustDeleteReferenceObjectsOneByOne()Return whether the reference objects must be deleted
one by one, as opposed to with a single DELETE statement.
ClassDescriptor referenceDescriptor = this.getReferenceDescriptor();
return referenceDescriptor.hasDependencyOnParts() || referenceDescriptor.usesOptimisticLocking() || (referenceDescriptor.hasInheritance() && referenceDescriptor.getInheritancePolicy().shouldReadSubclasses()) || referenceDescriptor.hasMultipleTables();
|
public void | postInsert(oracle.toplink.essentials.queryframework.WriteObjectQuery query)INTERNAL:
Insert the referenced objects.
// Insertion takes place according the the cascading policy
if (!this.shouldObjectModifyCascadeToParts(query)) {
return;
}
Object objects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
// insert each object one by one
ContainerPolicy cp = this.getContainerPolicy();
for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
Object object = cp.next(iter, query.getSession());
if (this.isPrivateOwned()) {
// no need to set changeSet as insert is a straight copy
InsertObjectQuery insertQuery = new InsertObjectQuery();
insertQuery.setObject(object);
insertQuery.setCascadePolicy(query.getCascadePolicy());
query.getSession().executeQuery(insertQuery);
} else {
// This will happen in a unit of work or cascaded query.
// This is done only for persistence by reachability and is not required if the targets are in the queue anyway
// Avoid cycles by checking commit manager, this is allowed because there is no dependency.
if (!query.getSession().getCommitManager().isCommitInPreModify(object)) {
ObjectChangeSet changeSet = null;
UnitOfWorkChangeSet uowChangeSet = null;
if (query.getSession().isUnitOfWork() && (((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet() != null)) {
uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet();
changeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(object);
}
WriteObjectQuery writeQuery = new WriteObjectQuery();
writeQuery.setObject(object);
writeQuery.setObjectChangeSet(changeSet);
writeQuery.setCascadePolicy(query.getCascadePolicy());
query.getSession().executeQuery(writeQuery);
}
}
}
|
public void | postUpdate(oracle.toplink.essentials.queryframework.WriteObjectQuery query)INTERNAL:
Update the reference objects.
if (!this.shouldObjectModifyCascadeToParts(query)) {
return;
}
// if the target objects are not instantiated, they could not have been changed....
if (!this.isAttributeValueInstantiated(query.getObject())) {
return;
}
// manage objects added and removed from the collection
Object objectsInMemory = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
Object objectsInDB = this.readPrivateOwnedForObject(query);
this.compareObjectsAndWrite(objectsInDB, objectsInMemory, query);
|
public void | preDelete(oracle.toplink.essentials.queryframework.WriteObjectQuery query)INTERNAL:
Delete the referenced objects.
// Deletion takes place according the the cascading policy
if (!this.shouldObjectModifyCascadeToPartsForPreDelete(query)) {
return;
}
// if referenced parts have their privately-owned sub-parts, delete them one by one;
// else delete everything in one shot
if (this.mustDeleteReferenceObjectsOneByOne() || query.shouldCascadeOnlyDependentParts()) {
Object objects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
ContainerPolicy cp = this.getContainerPolicy();
for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
Object object = cp.next(iter, query.getSession());
// Make sure only objects sheduled for deletion are deleted
if (shouldObjectDeleteCascadeToPart(query, object)) {
DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
deleteQuery.setObject(object);
deleteQuery.setCascadePolicy(query.getCascadePolicy());
query.getSession().executeQuery(deleteQuery);
}
}
if (!query.getSession().isUnitOfWork()) {
// This deletes any objects on the database, as the collection in memory may have been changed.
// This is not required for unit of work, as the update would have already deleted these objects,
// and the backup copy will include the same objects causing double deletes.
this.deleteReferenceObjectsLeftOnDatabase(query);
}
} else {
this.deleteAll(query);
}
|
public void | setDeleteAllSQLString(java.lang.String sqlString)PUBLIC:
Set the SQL string used by the mapping to delete the target objects.
This allows the developer to override the SQL
generated by TopLink with a custom SQL statement or procedure call.
The arguments are
translated from the fields of the source row, by replacing the field names
marked by '#' with the values for those fields at execution time.
A one-to-many mapping will only use this delete all optimization if the target objects
can be deleted in a single SQL call. This is possible when the target objects
are in a single table, do not using locking, do not contain other privately-owned
parts, do not read subclasses, etc.
Example: "delete from PHONE where OWNER_ID = #EMPLOYEE_ID"
DeleteAllQuery query = new DeleteAllQuery();
query.setSQLString(sqlString);
setCustomDeleteAllQuery(query);
|
public void | setSourceKeyFieldNames(java.util.Vector fieldNames)INTERNAL:
Set the source key field names associated with the mapping.
These must be in-order with the targetForeignKeyFieldNames.
Vector fields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size());
for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) {
fields.addElement(new DatabaseField((String)fieldNamesEnum.nextElement()));
}
setSourceKeyFields(fields);
|
public void | setSourceKeyFields(java.util.Vector sourceKeyFields)INTERNAL:
Set the source key fields.
this.sourceKeyFields = sourceKeyFields;
|
public void | setTargetForeignKeyFieldName(java.lang.String targetForeignKeyFieldName)PUBLIC:
Define the target foreign key relationship in the one-to-many mapping.
This method can be used when the foreign and primary keys
have only a single field each.
(Use #addTargetForeignKeyFieldName(String, String)
for "composite" keys.)
Only the target foreign key field name is specified and the source
(primary) key field is
assumed to be the primary key of the source object.
Because the target object's table must store a foreign key to the source table,
the target object must map that foreign key, this is normally done through a
one-to-one mapping back-reference. Other options include:
- use a DirectToFieldMapping and maintain the
foreign key fields directly in the target
- use a ManyToManyMapping
- use an AggregateCollectionMapping
this.getTargetForeignKeyFields().addElement(new DatabaseField(targetForeignKeyFieldName));
|
public void | setTargetForeignKeyFieldNames(java.lang.String[] targetForeignKeyFieldNames, java.lang.String[] sourceKeyFieldNames)PUBLIC:
Define the target foreign key relationship in the one-to-many mapping.
This method is used for composite target foreign key relationships.
That is, the target object's table has multiple foreign key fields to
the source object's (typically primary) key fields.
Both the target foreign key field names and the corresponding source primary
key field names must be specified.
if (targetForeignKeyFieldNames.length != sourceKeyFieldNames.length) {
throw DescriptorException.targetForeignKeysSizeMismatch(this);
}
for (int i = 0; i < targetForeignKeyFieldNames.length; i++) {
this.addTargetForeignKeyFieldName(targetForeignKeyFieldNames[i], sourceKeyFieldNames[i]);
}
|
public void | setTargetForeignKeyFieldNames(java.util.Vector fieldNames)INTERNAL:
Set the target key field names associated with the mapping.
These must be in-order with the sourceKeyFieldNames.
Vector fields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size());
for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) {
fields.addElement(new DatabaseField((String)fieldNamesEnum.nextElement()));
}
setTargetForeignKeyFields(fields);
|
public void | setTargetForeignKeyFields(java.util.Vector targetForeignKeyFields)INTERNAL:
Set the target fields.
this.targetForeignKeyFields = targetForeignKeyFields;
|
protected void | setTargetForeignKeysToSourceKeys(java.util.Map targetForeignKeysToSourceKeys)INTERNAL:
Set the target fields.
this.targetForeignKeysToSourceKeys = targetForeignKeysToSourceKeys;
|
protected boolean | shouldObjectModifyCascadeToParts(oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery query)Return whether any process leading to object modification
should also affect its parts.
Used by write, insert, update, and delete.
if (this.isReadOnly()) {
return false;
}
if (this.isPrivateOwned()) {
return true;
}
return query.shouldCascadeAllParts();
|
public boolean | verifyDelete(java.lang.Object object, oracle.toplink.essentials.internal.sessions.AbstractSession session)INTERNAL:
Used to verify whether the specified object is deleted or not.
if (this.isPrivateOwned()) {
Object objects = this.getRealCollectionAttributeValueFromObject(object, session);
ContainerPolicy containerPolicy = getContainerPolicy();
for (Object iter = containerPolicy.iteratorFor(objects); containerPolicy.hasNext(iter);) {
if (!session.verifyDelete(containerPolicy.next(iter, session))) {
return false;
}
}
}
return true;
|