Mapping one-to-many relationship with JPA 2.0, can be done in 2 ways:
- @OneToMany, with optional @JoinColumn
- @OneToMany with @JoinTable
Here I will look closer on option one, which is most common. @JoinTable is more common with @ManyToMany relationship/mapping.
_____________ _____________ | | | | | Employee | | Phone | |_____________| |_____________| | | | | | *employeeId | --> | *phoneId | | firstName | | *employeeId | |_____________| | areaCode | | | |_____________|
Bidrectional OneToMany Mapping
Now lets write some test code to test this.
And the debug output from Hibernate
As we can see the above create operation, generates 5 SQL statements (3 INSERTS and 2 UPDATES).
The same behavior with multiple INSERT followed by UPDATE, happens when you want to create a new Phone. Then you need to load the
Employee class and then call
addPhone(Phone). This is not optimal as you can see. Now lets consider another approach with unidirectional mapping.
First Attempt Unidirectional OneToMany Mapping
First we update our mapping annotations./p>
As we can see, we still need 5 SQL operations. But we can do better. Think how the underlying SQL is working. There is nothing magic when JPA or ORM. Lets first create parent
Employee and then create children
Phone and explicit set foreign key.
Second Attempt Unidirectional OneToMany Mapping
Mapping is the same, but "business logic" is changed.
As we can see the number of SQL statement is now reduced to the natural number that is sensible needed. And when we need to create a new child
Phone we do not need to load and add it to parent
Is there any downside with this solution. Not really if we would like bidirectional behavior we could add a
@Transient parameter and set it lazy, just as we would have done with if the mapping was bidirectional. One would maybe think of keeping bidirectional mapping eager, but that is not a good pattern/practice, since you could risk to load huge object graphs into memory, which would impact the performance negative.
The Rest of the Files
To make this complete here is the rest of the code.