ChatGPT解决这个技术问题 Extra ChatGPT

What is the "owning side" in an ORM mapping?

What exactly does the owning side mean? What is an explanation with some mapping examples (one to many, one to one, many to one)?

The following text is an excerpt from the description of @OneToOne in Java EE 6 documentation. You can see the concept owning side in it.

Defines a single-valued association to another entity that has one-to-one multiplicity. It is not normally necessary to specify the associated target entity explicitly since it can usually be inferred from the type of the object being referenced. If the relationship is bidirectional, the non-owning side must use the mappedBy element of the OneToOne annotation to specify the relationship field or property of the owning side.

I was lost until I read this: javacodegeeks.com/2013/04/…
The DB table with the foreign key column is treated as owning side. So the business entity representing that DB table is the Owner(Owning-side) of that relation. Not neccessarily, but most of the cases Owning-side will have @JoinColumn annotation.
This is not true. We can define foreign key on Many side with JoinColumn annotation on One side. In such case the owning side is One despite the foreign key being a column of the Many table

F
FUD

Why is the notion of a owning side necessary:

The idea of a owning side of a bidirectional relation comes from the fact that in relational databases there are no bidirectional relations like in the case of objects. In databases we only have unidirectional relations - foreign keys.

What is the reason for the name 'owning side'?

The owning side of the relation tracked by Hibernate is the side of the relation that owns the foreign key in the database.

What is the problem that the notion of owning side solves?

Take an example of two entities mapped without declaring a owning side:

@Entity
@Table(name="PERSONS")
public class Person {
    @OneToMany
    private List<IdDocument>  idDocuments;
}

@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
    @ManyToOne
    private Person person;
}

From a OO point of view this mapping defines not one bi-directional relation, but two separate uni-directional relations.

The mapping would create not only tables PERSONS and ID_DOCUMENTS, but would also create a third association table PERSONS_ID_DOCUMENTS:

CREATE TABLE PERSONS_ID_DOCUMENTS
(
  persons_id bigint NOT NULL,
  id_documents_id bigint NOT NULL,
  CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
  CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
  CONSTRAINT pk UNIQUE (id_documents_id)
)

Notice the primary key pk on ID_DOCUMENTS only. In this case Hibernate tracks both sides of the relation independently: If you add a document to relation Person.idDocuments, it inserts a record in the association table PERSON_ID_DOCUMENTS.

On the other hand, if we call idDocument.setPerson(person), we change the foreign key person_id on table ID_DOCUMENTS. Hibernate is creating two unidirectional (foreign key) relations on the database, to implement one bidirectional object relation.

How the notion of owning side solves the problem:

Many times what we want is only a foreign key on table ID_DOCUMENTS towards PERSONSand not the extra association table.

To solve this we need to configure Hibernate to stop tracking the modifications on relation Person.idDocuments. Hibernate should only track the other side of the relation IdDocument.person, and to do so we add mappedBy:

@OneToMany(mappedBy="person")
private List<IdDocument>  idDocuments;

What does it mean mappedBy ?

This means something like: "modifications on this side of the relation are already Mapped By the other side of the relation IdDocument.person, so no need to track it here separately in an extra table."

Are there any GOTCHAs, consequences?

Using mappedBy, If we only call person.getDocuments().add(document), the foreign key in ID_DOCUMENTS will NOT be linked to the new document, because this is not the owning /tracked side of the relation!

To link the document to the new person, you need to explicitly call document.setPerson(person), because that is the owning side of the relation.

When using mappedBy, it is the responsibility of the developer to know what is the owning side, and update the correct side of the relation in order to trigger the persistence of the new relation in the database.


The best answer i find that explains the Doctrine 'mappedBy' +'inversedBy'.
I don't know if things have changed, but on Hibernate 5.0.9.Final if I " only call person.getDocuments().add(document), " hibernate updates the foreign key in ID_DOCUMENTS.
@Karl Nicholas , hi, agree with you we have cascade attribute on @OneToMany annotation that can be set to PERSIST in this case hibernate will save all linked entities to the DB . Can anybody please clarify this - why author says that hibernate will not track changes on non owning side - but in fact hibernated performs tracking ?
cascade tells the provider to save the children entities even if the parent entity doesn't own them, so it effectively modifies the rule. If you had (or have) mappedBy=child.field and did NOT have cascade then the children of the list wouldn't be saved. Also, if you didn't have mappedBy AND didn't have cascade then the Parent owns the relationship and if you put NEW children in the list and then save the Parent it will throw an exception because the new children ID's aren't available to be saved in the join table. Hope that clarifies things ... :)
To further clarify CASCADE, it is about parent/child relationship rather than owner/owned. So it is unrelated to ownership. Ownership determines how to define/store the relationship in the database, in other words, in which table and column(s). Parent/child on the other hand, determines how an action(i.e. persist, remove) should propagate to the related entities. So for instance, for the Order - LineItem bi-directional relationship with CASCADE=REMOVE on the Order.LineItems property, when you remove the Order, LineItem (which is the owner) will be removed due to parent -> child cascade.
C
Community

You can imagine that the owning side is the entity that has the reference to the other one. In your excerpt, you have an one-to-one relationship. Since it's a symmetric relation, you'll end up having that if object A is in relation with object B then also the vice-versa is true.

This means that saving into object A a reference to object B and saving in object B a reference to object A will be redundant: that's why you choose which object "owns" the other having the reference to it.

When you have got an one-to-many relationship, the objects related to the "many" part will be the owning side, otherwise you would have to store many references from a single object to a multitude. To avoid that, every object in the second class will have a pointer to the single one they refer to (so they are the owning side).

For a many-to-many relationship, since you will need a separate mapping table anyway there won't be any owning side.

In conclusion the owning side is the entity that has the reference to the other.


Thank you for your clarification.
it might help to see bellow as well my answer for reasons for the names 'mappedBy' and 'owning side', what happens if we don't define a owning side, GOTCHAs, hope it helps
Well, the answer is mostly correct I guess. But for Hibernate at least, even many-to-many relationships have an owning side. This has implications for the updating behavior for example. Have a close look at section 4 ("Update Hibernate Model Class") of this tutorial: viralpatel.net/blogs/…
This answer confuses more than it helps. What good is it to say that "You can imagine that the owning side is the entity that has the reference to the other one" when in bidirectional relationships, both Entity objects will have a reference to each other? Also, "For a many-to-many relationship, since you will need a separate mapping table anyway there won't be any owning side" is just plain incorrect: @ManyToMany relationships have owning sides too. Similarly, @OneToMany relationships can use join tables, and you still have to specify an owning side.
Basically, this is a cute, feel-good answer that has upvotes because it's easier to understand than the truth.
d
debugmode

I will explaing about this very briefly. "Owning" means that carries the foreign key column in itself. In other words, it owns the relationship. Many people misunderstand the word owning. They think that the owning party is the main party. But when we look at it, the table with the foreign key column is the linked side. For example : Let's think about Person and Adress and relationship between them OneToOne

@Data
@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne
    @JoinColumn(name = "adress_id")
    private Adress adress;
}

@Data
@Entity
public class Adress {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToOne(mappedBy = "adress")
    private Person person;

}

in this case Person has adress_id fk column which linked of Adress of primary key column.

In general, you might be thinking why do I need the owning side? To understand this, you need to know database rules. For example, let's say you don't want to use an owning side and all data stores in one table and that means implementing a bad database practise. So I assume you now understand that each entity should store its own data in its own table. Now they are asking you to show the Person and his Address in the view section. How would you do it if there was no owning side? You would probably have to create 2 queries for each entity, right? Here, too, you have made a bad DML. Instead of writing 2 queries, you can write 1 query using JOIN. JOIN's work with the owning side we define, without them, we cannot select the data belonging to one table from the other table. ORM also offers you a more comfortable way by using basic java codes through entities without using databases. That's it.


V
Vishnu Shinde

Bidirectional relationships must follow these rules.

The inverse side of a bidirectional relationship must refer to its owning side by using the mappedBy element of the @OneToOne, @OneToMany, or @ManyToMany annotation. The mappedBy element designates the property or field in the entity that is the owner of the relationship.

The many side of many-to-one bidirectional relationships must not define the mappedBy element. The many side is always the owning side of the relationship.(According to Oracle docs : https://docs.oracle.com/cd/E19798-01/821-1841/bnbqi/index.html)

For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.

For many-to-many bidirectional relationships, either side may be the owning side.


f
fullstackdeveloper

Well that helps alot. I upvote this discussion

Especially I was looking for the following use case in Hospital Management System. Patient->Patient History 1.Patient is not dependent on patient history ie only in the first instance when Patient visited the hospital, his ailment history has to be added. 2. In subsequent visits the history gets added in history table but need a patient_id reference to Patient. So here as the foriegn key is in PatientHIstory table, the owning side is PatientHistory

So this relation has to be modelled Bi-Directional OneToMany, mappedby="patient" in patient Entity. Each of the entities refer to each other.


This is more of a comment than an answer. Probably better to leave a comment instead.