Hibernate Relationships

Author Avatar
Learn Here Fun Pedia
5 min read •
Featured Image

Hibernate Relationships

Hibernate Relationships is one of the most important areas because you need to understand both sides: the Java Application and the Relational Database.

In Java, objects can have direct relationships (e.g., Employee → Department). But a relational database doesn't store Java object references. Instead, it uses Primary Keys, Foreign Keys, and Join Tables.

Hibernate's job is to map:

Java Object Relationship
          ↕
      Hibernate
          ↕
Database Relationship
1 First Understand the Database Side

Before learning annotations, you must understand how relationships are represented in SQL. There are four major relationship types:

  • One-to-One
  • One-to-Many
  • Many-to-One
  • Many-to-Many

1. One-to-One

1.1 Meaning & 1.2 Database Representation

One record in Table A is associated with one record in Table B. For example, one Employee has one Passport.

A normal foreign key alone doesn't guarantee one-to-one mapping (as an employee could theoretically have multiple passports linked to them). Therefore, a true one-to-one relationship commonly uses:

FOREIGN KEY + UNIQUE constraint (e.g., employee_id UNIQUE)

1.3 & 1.4 Hibernate Representation & Owning Side

@Entity
public class Employee {
    @Id
    private Long id;

    @OneToOne
    @JoinColumn(name = "passport_id")
    private Passport passport;
}

This is extremely important: Who owns the relationship? Employee is the owning side because it contains the @JoinColumn. The side containing the foreign-key column generally controls the relationship mapping.

1.5 mappedBy

On the inverse side (Passport), we use @OneToOne(mappedBy = "passport"). This means: "The relationship is already mapped by the 'passport' field in the Employee entity." It does not create another foreign-key column.

2. One-to-Many & 3. Many-to-One

These two are actually reverse perspectives of the same database relationship. For example, One Department has Many Employees.

2.1 Database Representation

Notice something important: The foreign key is on the many side. (e.g., Employee.department_id points to Department.id).

Department                 Employee
    1                         *
    |                         |
    └──────────────<──────────┘
                         department_id

This is one of the most important database relationship rules: In a one-to-many relationship, the foreign key normally lives on the many side.

2.2 One-to-Many vs Many-to-One

This confuses many beginners. Don't think they are completely different database relationships. They are usually two Java perspectives of the same table relationship.

Department                    Employee
    1                            *
    |                            |
    | @OneToMany                 | @ManyToOne
    └──────────────<─────────────┘

4. Why Is @ManyToOne Usually the Owning Side?

Look at the database table for Employee. It contains the department_id. Therefore, the @ManyToOne mapping in the Employee class gets the @JoinColumn and acts as the owning side.

5. Many-to-Many

Now the relationship becomes: Many Employees work on Many Projects. One employee can work on multiple projects, and one project can have multiple employees (Employee * ↔ * Project).

5.1 & 5.2 Why We Need a Join Table

We cannot put a foreign key directly in Employee because a single project_id isn't enough to hold multiple projects. We need a separate association table (Join Table).

Employee
   *
   |
employee_project  ← (Join Table)
   |
   *
Project

5.3 & 5.4 Hibernate @ManyToMany & @JoinTable

@ManyToMany
@JoinTable(
    name = "employee_project",
    joinColumns = @JoinColumn(name = "employee_id"),
    inverseJoinColumns = @JoinColumn(name = "project_id")
)
private List
  • name: The join table name.
  • joinColumns: The foreign key pointing from the owning entity (employee_id).
  • inverseJoinColumns: The foreign key pointing toward the other entity (project_id).

6. Database Representation — The Big Picture

This is the part you should memorize conceptually:

One-to-One
Employee 1 ───── 1 Passport
(FK + UNIQUE)

One-to-Many / Many-to-One
Department 1 ───── * Employee
(FK is on the MANY side table)

Many-to-Many
Employee * ───── * Project
(Requires a Join Table)

7. & 8. Core Concepts to Remember

  • The Most Important Relationship Rule: In a ONE → MANY relationship, the foreign key normally goes on the MANY side.
  • mappedBy: It refers to the Java property name (not the database column name). It tells Hibernate "the other side owns this relationship."
  • Owning vs Inverse Side: The entity that has the actual foreign key in its database table generally owns the relationship.

9. Relationship Summary

Annotation Meaning Typical DB Representation
@OneToOne One ↔ One FK + usually UNIQUE constraint
@OneToMany One → Many FK on the many-side table
@ManyToOne Many → One FK on the many-side table
@ManyToMany Many ↔ Many Requires a Join table

The last three topics—Cascade, Fetch Type (LAZY/EAGER), and N+1 queries—are where Hibernate relationships move from simply knowing annotations to understanding real production behavior!

19. T3 Interview Questions You Should Be Able to Answer

Q: What is the difference between @OneToMany and @ManyToOne?

They are usually two perspectives of the exact same database relationship. @OneToMany is viewed from the "One" side (e.g., Department looking at Employees), while @ManyToOne is viewed from the "Many" side (e.g., Employee looking at its Department). The database structure is the same.

Q: How is a one-to-one relationship represented in a database?

It is represented by a Foreign Key column combined with a UNIQUE constraint. This ensures that one record in Table A is associated with exactly one record in Table B.

Q: What is the owning side?

The owning side is the entity that dictates the relationship mapping, usually because its corresponding database table contains the actual foreign-key column. It is designated by using the @JoinColumn annotation.

Q: What does `mappedBy` mean and why does it use the Java field name?

mappedBy is used on the inverse side of a bidirectional relationship. It tells Hibernate, "I don't control this relationship; look at the field named X on the other entity for the mapping rules." Because it points to the Java mapping logic on the other entity, it must use the Java property name, not the database column name.

Q: Why does many-to-many require a join table?

Because a single foreign key column can only point to one record. If an Employee works on multiple Projects, a single project_id column in the Employee table isn't enough. We need a separate table to hold multiple rows mapping various employee_ids to various project_ids.

Q: What is the difference between joinColumns and inverseJoinColumns?

In a @JoinTable, joinColumns defines the foreign key that points back to the entity that owns the association (the one you are currently writing the annotation in). inverseJoinColumns defines the foreign key pointing to the other (inverse) entity in the relationship.

img
➔ Read more about Hibernate Caching ➔ Read more about Fetch Types (LAZY vs EAGER) ➔ Read more about the N+1 Query Problem ➔ Read more about Cascading Operations

Comments (0)