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.