What Is the "Owning Side" in an Orm Mapping

What is the owning side in an ORM mapping?

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.

Owning Side vs Non-Owning Side In hibernate and its usage in reference of mapped by element?

Here is my understanding with simple example where College has many students(One to many relationship)

                       corresponds to       
College(Value Object) -----------------> College (Database Table)

corresponds to
Student(Value Object) -----------------> Student (Database Table having column which is
foreign key to College table .
So This is owning side and College is
Non-owning side )

In terms of Object representation, Student object is owning side becoz it will be having reference pointing to college column.So Student is owning side and College in non-owning side.

Usage of Owner side and Non-Owning side in hibernate in relation of mapped by element

Non-Owning Side Object

@Entity
public class College {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int collegeId;
@OneToMany(mappedBy="college") // here non-owning side using mapped by elment to specify
// the relationship field of owning side
private List<Student> students;
}

Owning Side Object

@Entity
public class Student {
@ManyToOne
private College college;
}

In conclusion the owning side is the entity that has the reference to the other. In terms of DB, it
translate to table entity having column which is foreign key to column in other table like in
case of College has many students.

Note:- owning-side table must contain a join column that refers to the other table's id.It means owning side entity should contain @joincolumn annotation otherwise it will consider the name as primary key column name of other table. See @OneToOne unidirectional and bidirectional

What is the owning side and inverse side in the doctrine 2 doc example

But I don't understand which entity (group or user) is the owning side

The User entity is the owner. You have the relation of groups in User:

/**
* @ManyToMany(targetEntity="Group", inversedBy="users")
* @JoinTable(name="users_groups")
*/
private $groups;

Look above, $groups var contains the all groups associated to this user, but If you notice the property definition, $groups var has the same name of mappedBy value (mappedBy="groups"), as you did:

/**
* @ManyToMany(targetEntity="User", mappedBy="groups")
*/
private $users;

What does mappedBy mean?

This option specifies the property name on the targetEntity that is the owning side of this relation.

JPA: which side should be the owning side in a m:n relationship?

Every bidirectional relationship requires an owning side in JPA. In the particular case of ManyToMany:

  • @JoinTable is specified on the owning side of the relationship.

    • the owning side is arbitrary, you can pick any of the two entities to be the owner.

From the JPA specification:

9.1.26 ManyToMany Annotation


Every many-to-many association has two
sides, the owning side and the
non-owning, or inverse, side. The join
table is specified on the owning side.
If the association is bidirectional,
either side may be designated as the
owning side.

Doctrine: owning side and inverse side

Take out all the things that have in your head about Owning side and Inversed side. These are nothing but some concepts that help Doctrine hydrate data into related models.

Read the following quotation from the Doctrine doc. This may somewhat help understand the concept of Owning side and Inversed side.

"Owning side" and "inverse side" are technical concepts of the ORM
technology, not concepts of your domain model. What you consider as
the owning side in your domain model can be different from what the
owning side is for Doctrine. These are unrelated.

Another quotation from the Doctrine doc:

Doctrine will only check the owning side of an association for
changes.

This means the owning side of an association is the entity with the table containing the foreign key. Therefore, the table containing foreign key will only be considered by doctrine for changes.

Once again from the Doctrine doc:

  • OneToOne - One instance of the current Entity refers to One instance of the referred Entity.
  • The owning side of a OneToOne assocation is the entity with the table containing the foreign key

Here one instance of Company refers to one instance of the referred entity Customer or vice versa.

When we talk about OneToOne association like your example above, the owning side would be the entity with the table containing the foreign key, therefore, Customer entity.

With your example, Doctrine will create tables like the below:

CREATE TABLE Company (
id INT AUTO_INCREMENT NOT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE Customer (
id INT AUTO_INCREMENT NOT NULL,
company_id INT DEFAULT NULL,
PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Customer ADD FOREIGN KEY (company_id) REFERENCES Company(id);

Now if you want to get data for a customer associated with a company then the query would be:

SELECT Company.id AS CompanyID, Customer.id AS CustomerID
FROM Company
LEFT JOIN Customer ON Company.id = Customer.company.id;

The returned result from this type of query will be hydrated into both models by Doctrine.

Trying to understand the importance of an owning side of a one-many relationship in ORM

With most ORM layers you have concept of lazy loading. When you create a Person object it will not load phones set unless asked to. At times how you want to lookup data can also dictate how you store it.

Like if you want to bring up person first and then show phone numbers on demand then keeping person references in phone is fine. First you fire a simple query to load person data and then just lookup phone numbers based on an (already loaded) person.id (another simple query)

Whereas for showing person + phone data at one go, you would prefer having a join table where you can just load data based on person table + person-phone join table using person id as keys into phone table, all in one go. Here it would be expensive to do lookups without a relationship table.

But quite frankly, if you think SQL instead of ORM then you would go with a relationship table every time :D

What does relationship owner means in bidirectional relationship?

Your first example is normal and correct bidirectional one-to-many/many-to-one mapping. Setting Question to Choice-attribute ("owning side") is enough to have relationship persisted. Entity graph in memory will be messed until other side of the relationship is read from database again. From the
database point-of-view owner is the entity that is persisted to table that have foreign key column (same for bidirectional one-to-one). In specification this is explained following way:

The many side of one-to-many / many-to-one bidirectional relationships
must be the owning side, hence the mappedBy element cannot be
specified on the ManyToOne annotation.

....

Bidirectional
relationships between managed entities will be persisted based on
references held by the owning side of the relationship. It is the
developer’s responsibility to keep the in-memory references held on
the owning side and those held on the inverse side consistent with
each other when they change. In the case of unidirectional one-to-one
and one-to-many relationships, it is the developer’s responsibility to
insure that the semantics of the relationships are adhered to.

In JPA terms your second example does not have owning side, because of absence of mappedBy. Instead you have two unidirectional relationships which are forced to use same column as store. At least with Hibernate 3.5.6 it will behave following way:

  • Setting Question to choice-attribute will not persist relationship.
  • Adding Choice to question-attribute will not persist relationship.
  • To persist value to "QUESTION_ID" both have to be set (yes, also not-insertable question).

What does owning side really mean?

Why I should duplicate the physical information? And why Troop table
doesn't contains troop_fk field (look at example above)

Between two entities you can have multiple relationships, like: Organisation has multiple employees, and Organisation is lead by multiple employees. Only if a relationship is bilateral you can speak about owning and non-owning side. Suppose that both relationships are bilateral, meaning that every entity has two fields each. Now it would be unclear for Hibernate to map those fields to two relationship. This is why this notion was introduced, to pair/assign the fields to the same relationhip.

Example:

public class Organisation {
@OneToMany(mappedBy="employeeOf")
private List<Employee> employees;
@OneToMany(mappedBy="leaderOf")
private List<Employee> leaders;
}

public class Employee {
@ManyToOne
@JoinColumn("organisationAsEmployee_id")
private Organisation employeeOf;
@ManyToOne
@JoinColumn("organisationAsLeader_id")
private Organisation leaderOf;
}

Suppose in Organisation.employees you wouldn't have mappedBy. Then Hibernate wouldn't know whether this field is in the same relationship with Employee.employeeOf or Employee.leaderOf or a single independent relationship (with no matching field in the Employee entity). And if it does not know that piece of information, it does not know how to join the tables, for example, or whether it has to create a new field or not.

Does Hibernate ignore all the queries on mapped (not owner) side?

Hibernate (JPA) ignores the @JoinColumn of the NOT-owner side, but not the cascading annotations. And a NOT-owner side MUST have a mappedBy property in the ManyToOne annotation (which you do not have => you do not have a bilateral relationship right now).

Does owner side implies some restrictions on the order in which
entites should be saved?

No.

Non-owning entity side of @OneToOne/@ManyToOne/@ManyToMany

In the bi-directional relationship betweens two objects ,you have to choose which sides to manage the relationship. From the database perspective , managing the relationship means managing the value of some FK column that link between two tables. The side that managing it is called owning side. Otherwise, it is call non-owning side.

So back to your example on ProjectManager and Project. Which object is the owning side depends on which object you choose to manage their relationship.

If you choose ProjectManager to be the owning side (hence Project is the non-owning side), only the values of ProjectManager#getProjects() will be used to determine the value of such FK column. (i.e. project table 's project_manager_id column in this case) The value of Project#getProjectManager() will be ignored and does not affect the value of this FK column.

In term of JPA mapping , it is :

@Entity
@Table(name="project_manager")
public class ProjectManager{

@OneToMany
private List<Project> projects = new ArrayList<>();

}

@Entity
@Table(name="project")
public class Project {

@ManyToOne
@JoinColumn(name = "project_manager_id")
private ProjectManager projectManager;
}

On the other hands , if you choose Project to the owning side (hence ProjectManager is the non-owning side) , only the value of Project#getProjectManager() will be used to determine the value of this FK column while the value of ProjectManager#getProjects() will be ignored. The JPA mapping in the case will be :

@Entity
@Table(name="project_manager")
public class ProjectManager{

@OneToMany(mappedBy="projectManager")
private List<Project> projects = new ArrayList<>();

}

@Entity
@Table(name="project")
public class Project {

@ManyToOne
@JoinColumn(name = "project_manager_id")
private ProjectManager projectManager;
}

P.S: I explain it using property access , hopefully you should get the idea.



Related Topics



Leave a reply



Submit