This relationship is essentially the same as Many to One relation, Unidirectional relation , but now we choose the opposite direction for navigating the connection. See here for Many to one unidirectional relation.
Thus our
As far as the database is concerned, there is no difference between this and the unidirectional
Now that entities are being stored in collections, it becomes critical that you have appropriately implemented
The simplest collection, for our purposes, is a
Here, we define a property of
There are a number of constraints imposed by the use of this
Finally, there is the question of why
Note that the association belongs to the
The solution is to only create such
Thus our
Lecturer
object now has a property which is a collection of Student
objects while the Student
objects have no properties which refer to their supervising Lecturer
.As far as the database is concerned, there is no difference between this and the unidirectional
many-to-one
association: there will still be a single column in the table holding the Student
objects that contains a foreign key into the table holding the Lecturer
objects. Now that entities are being stored in collections, it becomes critical that you have appropriately implemented
equals
and hashCode
methods for those entities. In particular, you should ensure that these methods are independent of the generated surrogate keys and that trivial changes to the object do not effect the methods while the objects are in the collections. The simplest collection, for our purposes, is a
Set
. To create the association, we add a Set
valued property to Lecturer
<set name="advisees" cascade="save-update" lazy="true"> <key column="lecturer_id"/> <one-to-many class="Student"/> </set>
Here, we define a property of
Lecturer
which is Set
valued. The name of the property is advisees
. This property is to capture a one-to-many
association to the Student
class and it this association is to be implemented in the database as a foreign key to the table holding Lecturer
objects stored in the column lecturer_id
in the table holding Student
objects. There are a number of constraints imposed by the use of this
one-to-many
association which arises from the fact that it is represented by this "reverse" link from the contained object side of the association: - From a Java point of view, we could potentially have two different
Lecturer
objects, both of which have the sameStudent
object in their container. However, this is not possible for aone-to-many
association because, in the database, eachStudent
row refers to the singleLecturer
row which contains it. If you want the true Java semantics, you have to represent the association as amany-to-many
one. - You cannot have the same object multiple times in the same collection. This is obvious when the collection property is of type
Set
, but one could use other types, such as List. However, the implementation of association by the reverse foreign key makes this impossible. Again, amany-to-many
association can provide the appropriate semantics
Finally, there is the question of why
one-to-many
associations between entities cause problems. Consider the following code:tx = session.beginTransaction(); Lecturer lect = new Lecturer("Gordon Brown") ; lect.getAdvisees().add(new Student("Tony Blair")) ; lect.getAdvisees().add(new Student("Michael Howard")) ; session.save(lect); tx.commit();
Note that the association belongs to the
Lecturer
class (as it is defined in Lecturer
's mapping file). This means that adding a student to a lecturer's advisees is considered an operation on a lecturer, not on a student. Thus the SQL statements that would be generated for the above statements would include an insert for the lecturer object, together with an insert each for the two connected student objects (because the students are referred to by the lecturer and we have put the cascade="save-update"
declaration in the Lecturer
's mapping file. But because the association does not belong to the students, the saving of the students would not set the foreign key value to the advising lecture. Thus there would be two extra update statements for adding the lecturer's foreign key value into the student records. These extra two update statements are not just an efficiency problem: If every student should have a supervisor, then we would like to add the not-null="true"
attribute to the key
element in the mapping file for the association. However this would cause errors as the above sequence of inserts and updates does insert nulls (if only to immediately update them) where they should never occur.The solution is to only create such
one-to-many
associations as the inverse end of a bidirectional many-to-one
association. This gives ownership of the association to the Student
end and, as we see below, leads to the foreign key being created as part of the initial insert of the Student
record instead of after it as a consequence of the Lecturer
insert.
No comments:
Post a Comment