Hibernate/JPA ManyToOne vs OneToMany

arjacsoh picture arjacsoh · Apr 20, 2013 · Viewed 29k times · Source

I am reading currently the documentation of Hibernate regarding the entity associations and I come accross a little difficulty to figure out some things. It has to do in essence with the difference between ManyToOne and OneToMany associations. Although I have used them in real projects, I cannot apprehend completely the differnce between them. To my understanding, if a table / an entity has a ManyToOne association with another, then the association should be from the other side OneToMany. So, how should we decide which one to choose based on a specific case and how does it affect the database/queries/results? Is there everywhere a good example?

P.S.: I reckon it would be helpful due to its relevance to the question, if someone could besides explain what is the point of the owner of the association and the difference between Bidirectional and Unidirectional association.

Answer

JB Nizet picture JB Nizet · Apr 20, 2013

Suppose you have an Order and an OrderLine. You can choose to have a unidirectional OneToMany between Order and OrderLine (Order would have a collection of OrderLines). Or you can choose to have a ManyToOne association between OrderLine and Order (OrderLine would have a reference to its Order). Or you can choose to have both, in which case the association becomes a bidirectional OneToMany/ManyToOne association.

The solution you choose mainly depends on the situation, and on the level of coupling between the entities. For example, if a user, a company, a provider all have many addresses, it would make sense to have a unidirectional between every of them and Address, and have Address not know about their owner.

Suppose you have a User and a Message, where a user can have thousands of messages, it could make sense to model it only as a ManyToOne from Message to User, because you'll rarely ask for all the messages of a user anyway. The association could be made bidirectional only to help with queries though, since JPQL queries join between entities by navigating through their associations.

In a bidirectional association, you could be in a situation where the graph of objects is inconsistent. For example, Order A would have an empty set of OrderLines, but some OrderLines would have a reference to the Order A. JPA imposes to always have one side of the association being the owner side, and the other side being the inverse side. The inverse side is ignored by JPA. The owner side is the side that decides what relation exists. In a OneToMany bidirectional association, the owner side must be the many side. So, in the previous example, the owner side would be OrderLine, and JPA would persist the association between the lines and the order A, since the lines have a reference to A.

Such an association would be mapped like this:

in Order :

@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the 
   // inverse side, and that the mapping is defined by the attribute parentOrder 
   // at the other side of the association.
private Set<OrderLine> lines;

in OrderLine :

@ManyToOne
private Order parentOrder;