ChatGPT解决这个技术问题 Extra ChatGPT

Hibernate/JPA ManyToOne vs OneToMany

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 comprehend completely the difference 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.


J
Jim Kiley

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;

m
marc_s

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.


a
axiopisty

While above answers are accurate, I will present the answer in a different way.

Both @OneToMany and @ManyToOne have two parts; left part and right part. For example:

@OneToMany = 'One' is left part and 'Many' is right part

@ManyToOne = 'Many' is left part and 'One' is right part

Simple rule of association using this understanding is, left part represents the class in which you are defining the association.

So, if you define @ManyToOne in OrderLine class referencing to Order class, it means many OrderLine associated to one Order class.


B
Byted

I will answer by an example. Suppose you have a design for an Ordering or a POS system. Then, each order has order details (e.g. products). In that case we have a @oneToMany relationship. The same will apply for a sale and sale details relationship.

If I have a user table and each user is tied to a specific shop then we can have many users tied to the same shop hence @manyToOne.