persistence@glassfish.java.net

Re: Uni-directional OneToMany entity mapping

From: Craig L Russell <Craig.Russell_at_Sun.COM>
Date: Thu, 11 Jan 2007 13:02:16 -0800

Hi Martin,

The portable way of mapping this in Java Persistence is to have a
relationship from TelephoneNumber to Customer. It's easier for the
persistence provider to manage the relationship if it's
bidirectional. The reason it's easier is just because of
implementations. I agree that from the user perspective it's easier
to use either uni- or bi-directional relationships, but the spec was
a compromise.

What is your concern with the bidirectional relationship? If it's
just a modeling issue, you can always make the relationship to
Customer private (field) or protected (field or property).

Craig

On Jan 11, 2007, at 12:21 PM, Martin Bayly wrote:

> I was trying to setup a uni-directional OneToMany mapping.
>
> An example of this mapping might be a customer's telephone numbers.
>
> e.g.
> CUSTOMER
> id
> name
>
> TELEPHONE_NUMBER
> id
> number
> cust_id (FK->CUSTOMER.id)
>
> In my entities I tried setting this up by adding a collection of
> TelephoneNumbers to my Customer entity and annotating it with a
> @OneToMany. The TelephoneNumber entity has no reference to the
> Customer entity.
>
> e.g. in Customer
>
> @OneToMany
> public List<TelephoneNumber> getTelephoneNumbers() {
> return this.telephoneNumbers;
> }
>
> However, this creates a join table instead which is not what I wanted.
>
> I tried adding an @JoinColumn(name="cust_id") annotation to the
> getTelephoneNumbers but TopLink complains that @JoinColumn is not
> valid.
>
> [TOPLINK-7160] (Oracle TopLink Essentials - 9.1 (Build b26)):
> oracle.toplink.essentials.exceptions.ValidationException
> Exception Description: @OneToMany for attribute name
> [telephoneNumbers] in entity class [class com.domain.Customer]
> should not have @JoinColumn(s) specified. In the case where the
> @OneToMany is not mapped by another entity (that is, it is the
> owning side and is uni-directional), it should specify (optional
> through defaulting) a @JoinTable.
>
> I'm not following this. It used to work when the relationship was
> bi-directional i.e. the TelephoneNumber had a reference to it's
> customer and I used @OneToMany(mappedBy="customer"). However, I
> don't want that additional reference.
>
> The book "Enterprise JavaBeans 3.0, 5th Edition" seems to indicate
> that the correct way to do a OneToMany uni-directional without join
> table is using @OneToMany and @JoinColumn.
>
> Also the Hibernate Entity Manager reference manual indicates this
> is also possible but has the following caveat that I don't really
> understand:
> "A unidirectional one to many using a foreign key column in the
> owned entity is not that common and not really recommended."
>
> So what's the deal here - it seems like this is a really normal
> thing to try and do. Using a FK column on the owned entity seems
> like the standard way to model a OneToMany relationship in a
> relational db - I don't see why the relationship should have to be
> bi-directional in JPA terms to achieve this modeling? What am I
> missing here? Why does the Hibernate manual say it's not recommended?
>
> Thanks for any insight.
> Martin Bayly

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell_at_sun.com
P.S. A good JDO? O, Gasp!