3. Relationship Mappings
1. @OneToOne
About
@OneToOne
defines a one-to-one relationship between two entity classes.It means each instance of Entity A is associated with exactly one instance of Entity B, and vice versa.
It is bidirectional or unidirectional based on how we model the relationship.
Syntax
This maps a simple unidirectional @OneToOne
— Employee has a link to EmployeeDetails.
Attributes
mappedBy
Indicates the inverse side of the relationship (used in bidirectional mapping).
cascade
Defines cascade operations like persist, remove, merge etc.
fetch
Defines when to fetch related entity: EAGER
(default) or LAZY
.
optional
Whether the relationship is mandatory (false
) or optional (true
). Default is true
.
orphanRemoval
Whether to automatically remove orphaned records.
How Relationships Are Stored in Database
Usually through a foreign key.
Typically one table has a foreign key reference to the other table.
For example:
1. Unidirectional @OneToOne
@OneToOne
Only one entity knows about the relationship.
@JoinColumn(name = "details_id", referencedColumnName = "id")
details_id
column inemployee
table holds the foreign key referencingemployee_details(id)
.
cascade = CascadeType.ALL
If we persist or delete an Employee, EmployeeDetails will automatically be persisted or deleted too.
2. Bidirectional @OneToOne
@OneToOne
Both entities are aware of the relationship.
EmployeeDetails
owns the relationship (@JoinColumn
is there).Employee
just references it throughmappedBy = "employee"
.mappedBy
tells JPA that the foreign key is managed by the other side (i.e., EmployeeDetails).
Cascade Types
We often want operations on the parent to affect the child entity too.
Typical cascade types with @OneToOne
:
CascadeType.PERSIST
: Save parent ➔ saves child.CascadeType.REMOVE
: Delete parent ➔ deletes child.CascadeType.MERGE
: Merge parent ➔ merges child.CascadeType.ALL
: All operations (persist, merge, remove, refresh, detach).
2. @OneToMany
About
@OneToMany
defines a one-to-many relationship between two entity classes.It means one instance of Entity A is associated with multiple instances of Entity B.
For example, one Department has many Employees.
Syntax
This is a unidirectional mapping — Department has a list of Employees.
Attributes
mappedBy
Specifies that this side is the inverse side (non-owning side).
cascade
Propagate operations (persist, merge, remove, etc.).
fetch
LAZY
(default) or EAGER
fetching behavior.
orphanRemoval
Automatically remove child records if they are no longer referenced.
How It Is Mapped in Database ?
Usually with a foreign key in the child table.
The
employee
table holds a foreign key (department_id
) pointing todepartment(id)
.
1. Unidirectional @OneToMany
@OneToMany
Only one side (Department) knows about the relationship. But foreign key is still in child table (Employee).
@JoinColumn(name = "department_id")
tells Hibernate to use department_id in the Employee table as a foreign key.Without
@JoinColumn
, Hibernate would create an unnecessary join table (bad for performance if not needed).cascade = CascadeType.ALL
will propagate persist, remove, etc.
2. Bidirectional @OneToMany
and @ManyToOne
@OneToMany
and @ManyToOne
Both sides know the relationship.
Department
is the inverse side (mappedBy = "department"
).Employee
owns the foreign key (@JoinColumn(name = "department_id")
).orphanRemoval = true
means if we remove an Employee from Department's employee list, Hibernate deletes it.
3. @ManyToOne
About
@ManyToOne
defines a many-to-one relationship between two entities.It means many instances of Entity A are associated with one instance of Entity B.
Example: Many Employees belong to one Department.
Syntax
This is a simple way to map Employee ➔ Department.
Attributes
fetch
Defines loading strategy: EAGER
(default) or LAZY
.
optional
Defines if the association is mandatory (false
) or optional (true
).
cascade
Defines cascading of operations (persist, merge, remove, etc.).
targetEntity
Defines the class type explicitly if necessary (rarely used).
How It Is Mapped in Database ?
The foreign key is created in the table of the owning entity (Employee).
employee.department_id
points todepartment.id
.
Entity Classes
@ManyToOne
is placed on the field in the owning entity (Employee).@JoinColumn(name = "department_id")
maps the foreign key column.fetch = FetchType.LAZY
means Department will not be loaded until needed.optional = false
means the Employee must have a Department (null not allowed).
4. @ManyToMany
About
@ManyToMany
defines a many-to-many relationship between two entities.It means many instances of Entity A are related to many instances of Entity B.
Example: Many Employees can work on many Projects.
Syntax
This creates a many-to-many relation between Student
and Course
Attributes
fetch
Defines loading strategy: LAZY
(default) or EAGER
.
cascade
Defines cascade operations on associated entities.
targetEntity
Explicitly defines associated class if needed.
How It Is Mapped in Database ?
JPA creates an intermediate join table to manage the association.
@ManyToMany always requires an intermediate join table because relational databases do not support direct many-to-many relations.
The join table holds two foreign keys:
One pointing to Entity A.
One pointing to Entity B.
The join table can optionally have a composite primary key (both foreign keys together).
1. Unidirectional @ManyToMany
Mapping
@ManyToMany
MappingOne Entity knows about the other.
The association is one-way.
Only the owning entity manages the relationship.
Other entity (target entity) does NOT know about the relation.
Generated Database Tables
student
id, name
id
-
course
id, title
id
-
student_course
student_id, course_id
(student_id, course_id) composite key
FK (student_id) → student(id) FK (course_id) → course(id)
Join Table (student_course) is fully managed by Student.
Course does not know anything about Students.
Important
Since
Course
does not have any@ManyToMany(mappedBy = ...)
, it is unaware of this relationship in Java model.
2. Bidirectional @ManyToMany
Mapping
@ManyToMany
MappingBoth Entities know about each other.
Association is two-way.
One side is the owning side (
@JoinTable
), and the other is the inverse side (mappedBy
).Only the owning side actually updates the join table in database.
In Java memory, both sides need to be manually synchronized.
Generated Database Tables
student
id, name
id
-
course
id, title
id
-
student_course
student_id, course_id
(student_id, course_id) composite key
FK (student_id) → student(id) FK (course_id) → course(id)
Same join table structure as unidirectional.
But now, both entities are aware of the relationship.
Hibernate still only uses the owning side (
Student
) to insert/update/delete rows in the join table.
5. @JoinColumn
About
@JoinColumn
is used to customize the foreign key column generated for an entity association (like@OneToOne
,@ManyToOne
, etc.).It defines how two tables are joined in the database by explicitly specifying:
The foreign key column name.
Referenced primary key column.
Without
@JoinColumn
, JPA uses default naming conventions (which can be confusing or inconsistent).
Where is @JoinColumn
Used ?
@JoinColumn
Used ?It is placed on the owning side of relationships:
@OneToOne
@ManyToOne
(Optionally) in
@OneToMany
+@JoinColumn
(to avoid a join table)
Also used in
@JoinTable
(for join table’s joinColumns and inverseJoinColumns).
Syntax of @JoinColumn
Composite Foreign Keys (Multiple @JoinColumns)
If we need multiple columns (composite foreign key), use @JoinColumns
:
Important Parameters
name
Name of the foreign key column in the owner’s table.
referencedColumnName
Name of the primary key column in the target entity. Default: "id".
nullable
Whether the foreign key can be NULL (default: true).
unique
Whether the foreign key must be UNIQUE.
insertable
Whether the foreign key column is included in SQL INSERT (default: true).
updatable
Whether the foreign key column is included in SQL UPDATE (default: true).
foreignKey
Specifies foreign key constraint name in database.
Example — @ManyToOne
with @JoinColumn
@ManyToOne
with @JoinColumn
Database Tables Generated:
department
id (PK), department_name
employee
id (PK), name, department_id (FK to department.id)
@JoinColumn(name = "department_id")
tells JPA to create a foreign key column named department_id in Employee table.It references the id column of Department table.
If @JoinColumn
is not given explicitly:
Hibernate defaults to
<association_property>_<referenced_primary_key>
.In above example:
department_id
would still happen automatically — but being explicit is better for clarity and control.
How @JoinColumn
behaves if missing ?
@JoinColumn
behaves if missing ?JPA will:
Generate a foreign key.
Guess a column name using entity field name and primary key.
Constraint name will be auto-generated.
It is considered good practice to always specify @JoinColumn
manually for:
Database readability.
Easier migrations.
Predictable schema.
6. @JoinTable
About
@JoinTable
is used to define the Join Table (i.e., intermediate table) when two entities have a many-to-many or sometimes one-to-many association.A Join Table is a separate table that holds foreign keys referencing the primary keys of the two associated tables.
@JoinTable
gives you full control over:The name of the intermediate table.
The join columns (owner side foreign key).
The inverse join columns (other side foreign key).
Where @JoinTable
is Used ?
@JoinTable
is Used ?Mostly in
@ManyToMany
mappings.Sometimes in
@OneToMany
(only if you want to manage the relation via a separate table instead of a foreign key directly).
Syntax of @JoinTable
Parameters
name
Name of the join table in DB.
joinColumns
Specifies the column that refers to the current (owning) entity’s primary key.
inverseJoinColumns
Specifies the column that refers to the other (inverse) entity’s primary key.
uniqueConstraints
Optional. Defines uniqueness constraints on join table columns.
indexes
Optional. Allows creating indexes on join table columns.
Example — @ManyToMany
using @JoinTable
@ManyToMany
using @JoinTable
Suppose we have two entities:
Employee
Project
An employee can work on multiple projects, and a project can have multiple employees.
Entity Classes:
Database Structure Generated
employee
id (PK), name
project
id (PK), project_name
employee_project
employee_id (FK to employee.id), project_id (FK to project.id)
The employee_project
table acts as a bridge table — no direct foreign key inside employee
or project
tables.
Ownership in @JoinTable
The entity where
@JoinTable
is defined is the owning side.The other entity is inverse side (no control over join table).
In example above:
Employee owns the relationship.
Project does not.
Last updated
Was this helpful?