sleske
sleske

Reputation: 83577

Why do Hibernate docs recommend to use a join table for a one-to-many relation?

I thought that the common way to model a one-to-many relation in a database is via a foreign key relationship (i.e. one customer with many orders -> order table gets a FK reference to customer table).

However, Hibernate recommends to use a join table to model such relationships:

A unidirectional one to many using a foreign key column in the owned entity is not that common and not really recommended. We strongly advise you to use a join table for this kind of association (as explained in the next section). This kind of association is described through a @JoinColumn.

http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-association

Why is this "not really recommended". I thought the using an FK was the standard, and that join tables are only used for many-to-many relationships?

I don't like to create a join table, because the data model will look like the relationship is many-to-many, when in fact it is one-to-many.

What is the reason for this recommendation in the Hibernate docs?

Upvotes: 9

Views: 3356

Answers (4)

bwtaylor
bwtaylor

Reputation: 392

The previous section in the Hibernate docs covers Bidirectional One-to-many relationships and describes what you are probably used to, with a standard foreign key on the many entity. As others have said, this answer is only appropriate when you explicitly want a unidirectional relationship.

You would only want unidirectionality if the many side must not be aware of the relationship. That means the class on the many side can't have an attribute to represent the relationship, almost by definition. So think of this problem as asking "how do I represent a one-to-many relationship without using the normal approach".

Wanting a unidirectional relationship like this certainly is somewhat unusual, but I can see situations where you might want it for decoupling, security, auditing, or immutability reasons. For example, lets say that you are modeling a clinical trial, and your classes are Patient and Medication, and during the trial you give one of a set of medications to each patient. You want any logic that operates on Patient to be completely decoupled to which Medication is allocated to them. So instead of using patient.setMedication() as you normally would, you create the join class MedicationPatientMap and call medication.getMedicationPatientMap().addPatient(patient). Then you can control access to the medication to patient one-to-many relationship with logic on the medication side.

I don't think Customer-Order is a good example of this, because normally our mental model of orders expect Customers to be reachable from it. And really, most of the time you aren't

Upvotes: 2

Ryan Stewart
Ryan Stewart

Reputation: 128779

I can't speak with any authority, but my take on it has always been that with unidirectional relationships, there's a higher probability that your Order will be at the receiving end of multiple such relationships. That also increases the probability that the Order will have nulls in some of those columns because the Order has been created, but other objects that can reference the Order either don't exist yet or never will. On that count, it's a question of normalization to move the FK columns out to another table. Then there's also the fact that it better mirrors the object relationships. In a unidirectional one-to-one from Foo -> Bar, you'd expect to find the FK in Foo, not in Bar, because that's where the ownership is in the object model. The same applies to a uni-one-to-many from Customer -> Order. Looking at the object model, you don't expect to see ownership represented in the Order, hence not in the Order table either.

Upvotes: 2

atrain
atrain

Reputation: 9255

This question has been asked and answered on the Hibernate forums: https://forum.hibernate.org/viewtopic.php?t=954178&highlight=unidirectional+null+foriegn+foreign+key. It appears to be less an issue fo DB design and more one of how Hibernate functions.

Upvotes: 5

GeorgeG
GeorgeG

Reputation: 248

The citation from the documentation you have postet describes a unidirectional @OneToMany association, which is a different thing. In such an association, you only have a reference from Customer to Orders, not vice verca. So mapping that kind of association should be done with a join table, holding the collection of Orders for each Customer.

I guess the association you are thinking of is more likely a @ManyToOne association, with having the reference from Order to Customer.

Note that if you want to model a bidirectional association, you can use the "mappedBy" attribute in the @OneToMany annotation.

Upvotes: 3

Related Questions