Skip Headers
Oracle TopLink Developer's Guide
10g Release 3 (10.1.3)
B13593-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
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:

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();