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.
According to book Pro JPA 2 the main difference between unidirectional @ManyToOne and @OneToOne is that in @OneToOne: Only one instance of the source entity can refer to the same target entity instance. In other words, the target entity instance is not shared among the source entity instances.
These two are both ending with creating the same relationship as below: It means there is no difference in one-to-many or many-to-one, except the angle that you are reading that from.
You can have multiple one-to-many associations, as long as only one is EAGER.
The @JoinColumn annotation helps us specify the column we'll use for joining an entity association or element collection. On the other hand, the mappedBy attribute is used to define the referencing side (non-owning side) of the relationship.
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;
Also, having @ManytoOne
side as the owner would require only n+1 queries while saving the associtions. Where n is the number of associations (many side).
Whereas having @OneToMany
as the owner, while inserting the parent entity (one side) with associations (many side) would result in 2*N + 1 queries. In which one query would be for insert of the association and other query would be for updating foreign key in the associated entity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With