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

4

9

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?

Boleyn answered 12/7, 2011 at 15:12 Comment(1)
Note: This is related to the question #2096498 . However, this asks about how to avoid the join table; I'm asking about why using one is recommended.Boleyn
S
5

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.

Savannahsavant answered 21/7, 2011 at 23:43 Comment(0)
I
3

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.

Iatric answered 12/7, 2011 at 15:20 Comment(4)
Sorry, can't follow you there. Yes, I was thinking about only having a reference "Customer -> (list of) Orders". What are you referring to with the "which is a different thing"? I think I need a one-to-many association, that's why I quoted the section on @OneToMany.Boleyn
I suspect what you're thinking of is a bidirectional relationship, where Order has a property identifying its owning Customer, and Customer has a property listing the Orders it owns. In that case, this comment about unidirectional relationships does not apply, and a foreign key is fine.Valona
I think the warning against foreign keys for unidirectional one-to-many is there because it involves having a column in the table which is not mapped to anything in the corresponding entity, which would be a bit weird. The absence of a mapping for that column suggests that the relationship is not an intrinsic part of the Order, in which case, why is the column in the Order's table?Valona
Because it isn't an answer, merely a minor addendum to George's perfectly fine answer.Valona
P
2

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.

Penneypenni answered 22/7, 2011 at 1:31 Comment(0)
A
2

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

Adulterer answered 24/7, 2011 at 19:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.