✅ Short Answer
@OneToMany(mappedBy=...)
marks the inverse side of a bidirectional relationship → it tells JPA the parent does not own the foreign key.@JoinColumn
marks the owning side → it defines where the foreign key is stored in the database.
🔎 Detailed Explanation
🔹 @JoinColumn
- Used on the owning side of the relationship, usually on
@ManyToOne
or unidirectional@OneToMany
. - Defines the physical foreign key column in the database.
- Example on owning side (
ChildEntity
):
@ManyToOne
@JoinColumn(name = "parent_id") // child owns the FK
private ParentEntity parent;
✅ Here, ChildEntity
is the owning side → it has the parent_id
column in its table.
🔹 @OneToMany(mappedBy=…)
- Used on the inverse side of a bidirectional relationship → parent’s collection references the owning side’s field.
- Tells JPA which field in the child owns the foreign key.
- Example on inverse side (
ParentEntity
):
@OneToMany(mappedBy = "parent") // "parent" field in ChildEntity owns the FK
private List<ChildEntity> children;
✅ mappedBy
points to the field name (parent
) in the owning entity.
🔹 What happens without mappedBy?
If you write @OneToMany
without mappedBy
, JPA assumes the parent owns the relationship and creates a join table, not a foreign key → leads to inefficient schema:
@OneToMany
private List<ChildEntity> children; // creates join table Parent_Children
🔹 Putting it all together: Bidirectional Mapping
@Entity
public class ParentEntity {
@OneToMany(mappedBy = "parent") // inverse side
private List<ChildEntity> children;
}
@Entity
public class ChildEntity {
@ManyToOne
@JoinColumn(name = "parent_id") // owning side → foreign key in child table
private ParentEntity parent;
}
📊 Comparison Table
Feature | @JoinColumn | @OneToMany(mappedBy=…) |
---|---|---|
Owns the relationship? | ✅ Yes (defines foreign key) | ❌ No (inverse, points to owner) |
Defines foreign key? | ✅ Yes | ❌ No |
Creates join table? | ❌ No | ❌ Not by itself, but missing mappedBy causes join table |
Used on which side? | Owning side (usually @ManyToOne) | Inverse side (usually @OneToMany) |
📌 Key Takeaways
✅ Use @JoinColumn
to define where the foreign key physically exists → owning side.
✅ Use @OneToMany(mappedBy=...)
to mark the inverse side, pointing to the owning side’s field.
✅ Bidirectional mappings need one owning side + one inverse side for proper persistence behavior.