Entity Relationships

Real data is connected. JPA maps those connections with @OneToMany , @ManyToOne , and @ManyToMany — plus @JoinColumn , fetch types, and cascading to control how the links behave.

Learn Entity Relationships in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Make sure you are comfortable mapping a single JPA entity with @Entity , @Id , and @Column before connecting entities together.

💡 Analogy: Picture each table as a box and a relationship as a line drawn between boxes. A many-to-one line means many child rows each point at one parent — like many order lines pointing at one order; the child carries the @JoinColumn "pointer." The one-to-many view is just looking down the same line from the parent. A many-to-many needs a little switchboard table in the middle because neither side can hold a single pointer.

Only one end of each line is "in charge" of writing it — that is the owning side.

The @ManyToOne child owns the foreign key; the @OneToMany parent uses mappedBy to point back. Keep both sides in sync in a helper method so the in-memory graph matches the database.

cascade propagates operations from parent to child; orphanRemoval deletes a child removed from the collection. Here is a plain-Java sketch of that ownership you can run.

When both sides have "many," neither row can hold a single pointer, so JPA uses a join table . The owning side declares it with @JoinTable ; the inverse side just uses mappedBy .

Answer: the @ManyToOne (child) side — it holds the @JoinColumn . The @OneToMany side is the inverse via mappedBy .

Answer: LAZY . To-many collections load only when accessed; to-one defaults to EAGER .

Answer: neither side can store a single foreign key for "many," so a separate link table holds pairs of keys.

🎯 YOUR TURN — Posts and Comments

Model a bidirectional one-to-many: one Post has many Comment s, with the comment owning the foreign key.

🧩 MINI-CHALLENGE — Authors and Books

Model a many-to-many between Author and Book with a book_author join table.

You can now connect entities with @OneToMany , @ManyToOne , and @ManyToMany , name foreign keys with @JoinColumn , choose the owning side with mappedBy , tune EAGER vs LAZY fetching, and manage child lifecycles with cascade and orphanRemoval.

Next up: Derived Queries & @Query — letting Spring Data turn method names and JPQL into SQL.

Practice quiz

Which annotation models the 'many' side that owns a foreign key column?

  • @ManyToOne
  • @OneToMany
  • @OneToOne
  • @ManyToMany

Answer: @ManyToOne. @ManyToOne sits on the child entity and, by default, owns the foreign key column referencing the parent.

In a bidirectional one-to-many, which side is typically the inverse (non-owning) side?

  • The @ManyToOne side
  • The @OneToMany side
  • Both sides equally
  • Neither side

Answer: The @OneToMany side. The @OneToMany collection side uses mappedBy and is the inverse side; the @ManyToOne side owns the foreign key.

What does @JoinColumn specify?

  • The primary key column
  • A unique index
  • The fetch strategy
  • The foreign key column name used for the association

Answer: The foreign key column name used for the association. @JoinColumn names the foreign key column that links the two tables.

What is the DEFAULT fetch type for @ManyToOne?

  • LAZY
  • EAGER
  • ASYNC
  • There is no default

Answer: EAGER. To-one associations (@ManyToOne, @OneToOne) default to EAGER fetching.

What is the DEFAULT fetch type for @OneToMany?

  • EAGER
  • BATCH
  • LAZY
  • JOIN

Answer: LAZY. To-many associations (@OneToMany, @ManyToMany) default to LAZY fetching.

What does the mappedBy attribute indicate?

  • The owning field on the other entity
  • The join table name
  • The cascade type
  • The fetch mode

Answer: The owning field on the other entity. mappedBy points to the field on the owning side, marking this side as the inverse (non-owning) side.

Which relationship requires a join table by default?

  • @ManyToOne
  • @OneToOne
  • @ManyToMany
  • @OneToMany unidirectional with @JoinColumn

Answer: @ManyToMany. @ManyToMany cannot be expressed with a single foreign key, so it uses a separate join table.

What does cascade = CascadeType.ALL do on a parent's collection?

  • Deletes the database
  • Propagates persist, merge, remove, etc. to the children
  • Disables lazy loading
  • Makes the relationship read-only

Answer: Propagates persist, merge, remove, etc. to the children. CascadeType.ALL propagates all entity operations (persist, merge, remove, refresh, detach) from parent to children.

What problem does orphanRemoval = true solve?

  • N+1 queries
  • Eager fetching
  • Unique constraints
  • Deleting a child removed from the parent's collection

Answer: Deleting a child removed from the parent's collection. orphanRemoval deletes a child row once it is removed from the owning collection and no longer referenced.

Why is LAZY often preferred for associations?

  • It always loads everything immediately
  • It avoids loading related data until it is actually used
  • It removes foreign keys
  • It is required by JPA

Answer: It avoids loading related data until it is actually used. LAZY fetching defers loading related entities until accessed, avoiding unnecessary queries and large result sets.