Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA - difference in the use of the mappedBy property to define the owning entity

What exactly is the difference in the following two declarations

B is the owning side

@Entity
class A {
   @Id int id;

   @OneToOne
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne(mappedBy="b")
   A a;
}

A is the owning side

@Entity
class A {
   @Id int id;

   @OneToOne(mappedBy="a")
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne
   A a;
}

Thinking of this in "normal SQL" i think it is the same as having two tables each having the other table's foreign key. What i don't understand though is what is the effect of specifying which entity is the owning side i.e using the 'mappedBy' property. What does this actually achieve as i don't believe there is an equivalent in normal SQL.

like image 722
ziggy Avatar asked Jun 10 '12 12:06

ziggy


People also ask

What is the difference between @JoinColumn and mappedBy?

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.

What is the use of mappedBy in JPA?

The purpose of the MappedBy parameter is to instruct JPA: Do NOT create another join table as the relationship is already being mapped by the opposite entity of this relationship.

What is owning side in JPA?

The owning side is responsible for propagating the update of the relationship to the database. Usually this is the side with the foreign key. The inverse side maps to the owning side.


2 Answers

The owning side is the side that JPA considers to know is the association exists or not. Suppose you go with your first example. The owning side is the side where there is no mappedBy attribute. The owning side is thus A, and not B.

This means that if you have an A and a B in database, and you do

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
a.setB(b);

JPA will save the association (i.e. it will store the ID of B in the join column of table A).

But if you do

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
b.setA(a);

nothing will be changed in database, because you modified the inverse side and forgot to modify the owning side.

like image 110
JB Nizet Avatar answered Sep 28 '22 17:09

JB Nizet


The JPA 2.0 specification, section 2.9, writes:

Relationships may be bidirectional or unidirectional. A bidirectional relationship has both an owning side and an inverse (non-owning) side. A unidirectional relationship has only an owning side. The owning side of a relationship determines the updates to the relationship in the database, as described in section 3.2.4.

The following rules apply to bidirectional relationships:

  • The inverse side of a bidirectional relationship must refer to its owning side by use of 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 one-to-many / many-to-one bidirectional relationships must be the owning side, hence the mappedBy element cannot be specified on the ManyToOne annotation.
  • 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.

The relevant parts of section 3.2.4 are:

The state of persistent entities is synchronized to the database at transaction commit. This synchronization involving writing to the database any updates to persistent entities and their relationships as specified above.

and

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.

It is particularly important to ensure that changes to the inverse side of a relationship result in appropriate updates on the owning side, so as to ensure the changes are not lost when they are synchronized to the database.

like image 24
meriton Avatar answered Sep 28 '22 17:09

meriton