This week's book giveaway is in the OCPJP forum. We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line! See this thread for details.
I am just starting with ORM and JPA using Hibernate and have a question regarding managing the one-to-many relationship.
On the ONE side of the relationship we have getCollection() : Collection. On the MANY side we have a setter. Calling ONE.getCollection().add(...) does NOT update the many side by calling a corresponding setter. Calling the many side setter, does not perform getCollection().add(...). So, the two operations are not "mirror" of each other as otherwise expected. How are people working around this issue?
Do you implement the setter on the Many side to call back on the ONE.getCollection.add(this) and vice versa?
Yes, if you have bi-directional relationships in JPA, then you will need to set the link on both objects as you described, e.g.
The two options seem to be either update the setter methods on both objects so they update both objects, or alternatively you could just try and remember to include the calls to the two seperate setter methods throughout your application code everytime you update
Care should obviously be taken when updating the setter methods as you are at risk of having infinite cyclical calls, so make sure you put in the necessary checks, e.g.
Then do something similar on the setOne() method call on your Many class.
I get what you are saying with the code sample provided, however, m from your example could be associated with a different ONE. So, there is now a concept of oldONE and newONE. Thus we now need to remove from the old and add to the new. In addition a user of the class can call getMany() collection directly and add to it bypassing the addMany API entirely, so the collection needs to be returned as immutable. As you pointed out great care must be taken to do this without causing an infinite recursion. Since I am just starting out with this stuff, I am curious as to what people do. Do you write this type of code for every association?
This seems like a common pattern that would exist when ever you have bi-directional One-To-Many relationships. Do you know if there is anything in Spring that templates this?
ORM should not be a one-to-one mapping from the ER model to the Java object model, it is not something like an ActiveRecord but more like a translation between two different but related worlds. E.g. in ER every many-to-many association can be used somehow bidirectional, but this doesn't mean that it should be modeled as bidirectional association in the Java object model. Most tools that create a Java object model from tables automatically make all associations bidirectional as there is no hint in the ER about possible navigation. So such generated object models should be used as a first start only and modified heavily, if used at all.
It is your task to ensure the Java object model is consistent. This is much easier if you use less bidirectional associations, obviously. If a user of your class should not modify the underlying association collections then you shouldn't hand them out, just immutable collections, iterators or an interface that allows modification (i.e. add..., remove...). So the method rob showed is the standard way to go if you use this technology.
Alex Paransky J
Joined: May 23, 2011
So, suppose I have a Department (1) -has- (n) Employee relationship (one department OneToMany Employee) that I am trying to model. I have the tables for Employee with a department_id as FK and department table.
If I map these as a bi-directional relationship, then from Employee I can get to department using Employee.getDepartment() : Department and from Department I can get all people using Department.getEmployees() : Collection<Employee>. Alternatively, I can use a Unidirectional mapping and only have the path from Employee to Department, but not have a collection in the Department representing the Employee. Of course, to get all the employees for the department I would need to use a query instead of just calling Department.getEmployees(). Is this what you mean? Which method is preferred?