Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA JoinColumn vs mappedBy

What is the difference between:

@Entity public class Company {      @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY)     @JoinColumn(name = "companyIdRef", referencedColumnName = "companyId")     private List<Branch> branches;     ... } 

and

@Entity public class Company {      @OneToMany(cascade = CascadeType.ALL , fetch = FetchType.LAZY,      mappedBy = "companyIdRef")     private List<Branch> branches;     ... } 
like image 403
Mike Avatar asked Aug 13 '12 16:08

Mike


People also ask

What is difference between mappedBy and @JoinColumn?

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 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 JoinColumn in JPA?

JPA JAVA EE. @JoinColumn is used to specify a column for joining an entity association or element collection. This annotation indicates that the enclosing entity is the owner of the relationship and the corresponding table has a foreign key column which references to the table of the non-owning side.

What is the purpose of @JoinColumn?

Annotation Type JoinColumn. Specifies a column for joining an entity association or element collection. If the JoinColumn annotation itself is defaulted, a single join column is assumed and the default values apply. (Optional) The SQL fragment that is used when generating the DDL for the column.


2 Answers

The annotation @JoinColumn indicates that this entity is the owner of the relationship (that is: the corresponding table has a column with a foreign key to the referenced table), whereas the attribute mappedBy indicates that the entity in this side is the inverse of the relationship, and the owner resides in the "other" entity. This also means that you can access the other table from the class which you've annotated with "mappedBy" (fully bidirectional relationship).

In particular, for the code in the question the correct annotations would look like this:

@Entity public class Company {     @OneToMany(mappedBy = "company",                orphanRemoval = true,                fetch = FetchType.LAZY,                cascade = CascadeType.ALL)     private List<Branch> branches; }  @Entity public class Branch {     @ManyToOne(fetch = FetchType.LAZY)     @JoinColumn(name = "companyId")     private Company company; } 
like image 152
Óscar López Avatar answered Oct 13 '22 05:10

Óscar López


@JoinColumn could be used on both sides of the relationship. The question was about using @JoinColumn on the @OneToMany side (rare case). And the point here is in physical information duplication (column name) along with not optimized SQL query that will produce some additional UPDATE statements.

According to documentation:

Since many to one are (almost) always the owner side of a bidirectional relationship in the JPA spec, the one to many association is annotated by @OneToMany(mappedBy=...)

@Entity public class Troop {     @OneToMany(mappedBy="troop")     public Set<Soldier> getSoldiers() {     ... }  @Entity public class Soldier {     @ManyToOne     @JoinColumn(name="troop_fk")     public Troop getTroop() {     ... }  

Troop has a bidirectional one to many relationship with Soldier through the troop property. You don't have to (must not) define any physical mapping in the mappedBy side.

To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is not optimized and will produce some additional UPDATE statements.

@Entity public class Troop {     @OneToMany     @JoinColumn(name="troop_fk") //we need to duplicate the physical information     public Set<Soldier> getSoldiers() {     ... }  @Entity public class Soldier {     @ManyToOne     @JoinColumn(name="troop_fk", insertable=false, updatable=false)     public Troop getTroop() {     ... } 
like image 27
Mike Avatar answered Oct 13 '22 06:10

Mike