Tuesday, July 5, 2011

Many-to-One, Unidirectional Associations

This corresponds to the standard Java reference to one object from another.
A Many-to-One, Unidirectional Association

In the diagram above, we represent the relationship between students and their thesis supervisors. In this design, a student can have no more than one supervisor but may not (yet) have any. However, a lecturer may have any number, including zero, of students to supervise. Furthermore, we only allow a one directional link: Student has a property (say getSupervisor/setSupervisor) but there is no direct way, starting with a Lecturer object, to find the students that the lecturer supervises.
If we start with the simple, non-related, base entity mapping files for Student and Lecturer, we add this association by adding the following, as a sub-element of the class element, to the mapping file for Student:

<many-to-one name="supervisor"    column="supervisor"/>

This element acts very much like a normal property element in that it defines the mapping between the supervisor property of Student and the column in the students table. However, it also sets up the relationship so that, after getting a Student object from the database, if we use the supervisor accessor of that Student object, we will get the corresponding Lecturer object (or a proxy thereof if we have enabled lazy loading of the Lecturer objects). Finally, it ensures that the underlying database is created with a foreign key constraint that the supervisor column is a foreign key into the lecturers table.
As things stand, there is now a question of what you want the cascade behaviour of the relationship to be (see the section on cascade above). Without adding the optional cascade attribute to the many-to-one element, then the Lecturer object on the other end of the association is ignored when the Student object is saved, updated, deleted or when its supervisor property is reset away from it. Certainly we would not want the lecturer to be removed from the database when the student is deleted or when the student no longer has that lecturer as his or her supervisor; so none of the delete or all options are appropriate. But what about save-update?. There are two scenarios under which this might have an effect:
  1. If you create a new (transient) lecturer and make a persistent student refer to it. In fact, for this particular object design, one would never do such a thing: the obvious semantics of the situation dictate that you cannot just invent new lecturers on demand: you would always have to have the lecturer as a currently existing object in the database before setting the student's supervisor property to that lecturer. Since the scenario will never arise, this is neither a vote for or against using the save-update option.
  2. If the Student, and associated Lecturer objects were detached, and now you reattach the Student object, then you need the save-update option if you want the Lecturer object to be reattached automatically. Without that, you need to reattach it directly yourself — an easy task to overlook and therefore a source of bugs. This therefore, is a vote for set the cascade="save-update" option.

Note that you can specify unique="true" as an attribute of the many-to-one element. This has the effect of disallowing the possibility of having two student rows with the same supervisor values, i.e., turning the "*" on the Student side of the class diagram into a "0..1" or limiting each lecturer to having at most one supervisee. Similarly, specifying not-null="true" adds the requirement that every student must have a valid supervisor, i.e., it changes the "0..1" on the Lecturer side of the diagram to a "1".

No comments:

Post a Comment