hibernate-014: Why Did Hibernate Introduce Unidirectional and Bidirectional Relationships?
Hunor Vadasz-Perhat

Hunor Vadasz-Perhat @hunor85

About: Software Engineer II @DXC Technology

Location:
Denmark
Joined:
Jul 3, 2023

hibernate-014: Why Did Hibernate Introduce Unidirectional and Bidirectional Relationships?

Publish Date: Feb 10
0 2

🚀 Why Did Hibernate Introduce Unidirectional and Bidirectional Relationships?

Hibernate introduced unidirectional and bidirectional relationships to give developers flexibility in how they model database relationships in Java, without always needing explicit database joins or additional queries.

📌 The Key Reasons Hibernate Introduced These Concepts

Concept Why Was It Introduced?
Unidirectional Relationships (@ManyToOne, @OneToMany, @OneToOne) ✅ Simpler, aligns with database foreign keys, prevents unnecessary complexity.
Bidirectional Relationships (@OneToMany + @ManyToOne) ✅ Allows navigation in both directions, improves query flexibility.
Mapped Relationships (mappedBy) ✅ Helps define ownership, preventing unnecessary joins and redundant data storage.
Lazy vs. Eager Fetching ✅ Avoids performance problems by only loading what is necessary.

1️⃣ Hibernate Aligns with Relational Databases

  • In a relational database, foreign keys are always stored on the "many" side (e.g., customers.salesRepEmployeeNumber).
  • Hibernate allows us to model this naturally with @ManyToOne (child → parent).
  • But sometimes we also need to navigate from parent to child, so @OneToMany(mappedBy) was introduced.

2️⃣ Unidirectional vs. Bidirectional: The Trade-off

💡 Hibernate allows both unidirectional and bidirectional relationships to provide flexibility.

Feature Unidirectional (@ManyToOne) Bidirectional (@OneToMany + @ManyToOne)
Database-Friendly? ✅ Yes (Foreign Key is in the child table, natural) ⚠️ Yes, but can cause extra queries if misused
Hibernate Complexity ✅ Simple (follows normal FK logic) ⚠️ More complex (needs mappedBy)
Query Flexibility ❌ Only from child → parent (customer.getSalesRep()) ✅ Can fetch parent → child (employee.getCustomers())
Performance ✅ Efficient for querying parents ⚠️ Can cause N+1 query problems if not optimized
When to Use? ✅ When only one-way navigation is needed ✅ When you need to query in both directions

👉 Hibernate introduced unidirectional to keep things simple when bidirectionality is not needed.

👉 Hibernate introduced bidirectional for situations where both entities must be accessible from each other.


3️⃣ Hibernate Optimizes Object-Oriented Modeling

In a pure Java application, there are no foreign keys—only references between objects.

💡 Hibernate allows us to model database relationships in Java as natural object references.

Instead of writing manual SQL queries with joins, Hibernate automates relationships like:

Customer customer = entityManager.find(Customer.class, 1);
Employee salesRep = customer.getSalesRep();
Enter fullscreen mode Exit fullscreen mode

Instead of writing:

SELECT * FROM employees e
JOIN customers c ON e.employeeNumber = c.salesRepEmployeeNumber
WHERE c.customerNumber = 1;
Enter fullscreen mode Exit fullscreen mode

👉 Hibernate gives Java-like relationships on top of relational data storage.


4️⃣ Preventing Redundant Join Tables

Before Hibernate, manual join tables were often needed for relationships.

Hibernate introduced @JoinColumn to control where foreign keys are stored.

  • Without @JoinColumn on @OneToMany, Hibernate would create a join table (employee_customers).
  • With @JoinColumn, Hibernate simply stores the FK in the child table (customers.salesRepEmployeeNumber).

👉 Hibernate gives control over how relationships are stored in SQL, reducing unnecessary tables.


5️⃣ Preventing Infinite Recursion in JSON (Serialization)

One side effect of bidirectional relationships is infinite recursion in REST APIs.

Example:

{
    "employeeNumber": 1002,
    "customers": [
        {
            "customerNumber": 1,
            "salesRep": { "employeeNumber": 1002, "customers": [...] }
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

💡 Hibernate introduced @JsonManagedReference and @JsonBackReference to fix this issue!


🎯 Final Answer: Why Did Hibernate Introduce These Concepts?

  1. To align Java modeling with relational databases (Foreign keys, Parent-Child relationships).
  2. To offer flexibility—some use cases require bidirectional navigation, others don’t.
  3. To reduce extra join tables—Hibernate lets us control foreign key storage.
  4. To optimize performance—lazy loading, avoiding unnecessary queries.
  5. To simplify object-oriented relationships—Java developers can work with objects instead of raw SQL.

💡 Hibernate is about making object relationships feel "natural" while still being efficient in SQL.

Comments 2 total

  • Cies Breijs
    Cies BreijsFeb 10, 2025

    I'm against using an ORM. It's not easy to explain why in a couple of words, so I wrote a blog about it. I'd be interested what y'all think of it (I'm just now getting into blogging). dev.to/cies/the-case-against-orms-...

    • Hunor Vadasz-Perhat
      Hunor Vadasz-PerhatFeb 11, 2025

      Your article had some good points, that definitely need to be considered, when deciding whether an ORM is a good investment or not 😎

Add comment