Skip Headers

Oracle TopLink Developer's Guide 10g Release 3 (10.1.3) B13593-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# Associating a New Target to an Existing Source Object

There are two ways to associate a new target object with an existing source object with one-to-many and one-to-one relationships:

- Associating Without Reference to the Cache Object

- Associating With Reference to the Cache Object

Deciding which approach to use depends on whether or not your code requires a reference to the cache copy clone of the new object after the unit of work is committed, and on how adaptable to change you want your code to be.

## Associating Without Reference to the Cache Object

Example 101-5 shows the first way of associating a new target with an existing source.

Example 101-5 Associating Without Reference to the Cache Object

    UnitOfWork uow = session.acquireUnitOfWork();
        Pet petClone = (Pet)uow.readObject(Pet.class);

        PetOwner petOwner = new PetOwner();
        petOwner.setId(400);
        petOwner.setName("Donald Smith");
        petOwner.setPhoneNumber("555-1212");

        VetVisit vetVisit = new VetVisit();
        vetVisit.setId(500);
        vetVisit.setNotes("Pet was shedding a lot.");
        vetVisit.setSymptoms("Pet in good health.");
        vetVisit.setPet(petClone);

        petClone.setPetOwner(petOwner);
        petClone.getVetVisits().addElement(vetVisit);
    uow.commit();

This executes the proper SQL:

    INSERT INTO PETOWNER (ID, NAME, PHN_NBR) VALUES (400, 'Donald Smith', '555-1212')
    UPDATE PET SET PET_OWN_ID = 400 WHERE (ID = 100)
    INSERT INTO VETVISIT (ID, NOTES, SYMPTOMS, PET_ID) VALUES (500, 'Pet was shedding a lot.', 'Pet in good health.', 100)

When associating new objects to existing objects, the unit of work treats the new object as if it were a clone. That is, after the commit transaction:

    petOwner != session.readObject(petOwner)

For a more detailed discussion of this fact, see "Using registerNewObject").

Note: You cannot use `UnitOfWork` methods `registerObject`, `registerNewObject`, or `registerExistingObject` with an aggregate object (see "Relational Aggregate Descriptors"). Doing so will raise a `ValidationException` or other errors at commit time. For more information, see "Working with Aggregates".

Therefore, after the unit of work commit transaction, the variables `vetVisit` and `petOwner` no longer point to their respective cache objects; they point at working copy clones.

If you need the cache object after the unit of work commit transaction, you must query for it or create the association with a reference to the cache object (as described in "Associating With Reference to the Cache Object").

## Associating With Reference to the Cache Object

Example 101-6 shows how to associate a new target with an existing source with reference to the cache object.

Example 101-6 Associating With Reference to the Cache Object

    UnitOfWork uow = session.acquireUnitOfWork();
        Pet petClone = (Pet)uow.readObject(Pet.class);

        PetOwner petOwner = new PetOwner();
        PetOwner petOwnerClone = (PetOwner)uow.registerObject(petOwner);
        petOwnerClone.setId(400);
        petOwnerClone.setName("Donald Smith");
        petOwnerClone.setPhoneNumber("555-1212");

        VetVisit vetVisit = new VetVisit();
        VetVisit vetVisitClone = (VetVisit)uow.registerObject(vetVisit);
        vetVisitClone.setId(500);
        vetVisitClone.setNotes("Pet was shedding a lot.");
        vetVisitClone.setSymptoms("Pet in good health.");
        vetVisitClone.setPet(petClone);

        petClone.setPetOwner(petOwnerClone);
        petClone.getVetVisits().addElement(vetVisitClone);
    uow.commit();

Now, after the unit of work commit transaction:

    petOwner == session.readObject(petOwner)

This means that we have a handle to the cache copy after the commit transaction, rather than a clone.

Example 101-7 shows how to use unit of work method `registerNewObject` to add a new object when a bidirectional relationship exists. For more information, see "Using registerNewObject".

Note: You cannot use `UnitOfWork` methods `registerObject`, `registerNewObject`, or `registerExistingObject` with an aggregate object (see "Relational Aggregate Descriptors"). Doing so will raise a ValidationException or other errors at commit time. For more information, see "Working with Aggregates".

Example 101-7 Resolving Issues When Adding New Objects

    // Get an employee read from the parent session of the unit of work
    Employee manager = (Employee)session.readObject(Employee.class);

    // Acquire a unit of work
    UnitOfWork uow = session.acquireUnitOfWork();

    // Register the manager to get its clone
    Employee managerClone = (Employee)uow.registerObject(manager);

    // Create a new employee
    Employee newEmployee = new Employee();
    newEmployee.setFirstName("Spike");
    newEmployee.setLastName("Robertson");

    /* INCORRECT: Do not associate the new employee with the original manager. This will cause a QueryException when TopLink detects this error during  commit */
    //newEmployee.setManager(manager);

    /* CORRECT: Associate the new object with the clone. Note that in this example, the setManager method is maintaining the bidirectional managedEmployees relationship and adding the new employee to its managedEmployees. At commit time, the unit of work will detect that this is a new object and will take the appropriate action */
    newEmployee.setManager(managerClone);

    /* INCORRECT: Do not register the newEmployee: this will create two copies and cause a QueryException when TopLink detects this error during commit */
    //uow.registerObject(newEmployee);

    /* CORRECT:
    In the above setManager call, if the managerClone's managedEmployees was not
    maintained by the setManager method, then you should call registerObject before the new employee is related to the manager. If in doubt, you could use the  registerNewObject method to ensure that the newEmployee is registered in the unit of work. The registerNewObject method registers the object, but does not make a clone */
    uow.registerNewObject(newEmployee);

    // Commit the unit of work
    uow.commit();