mappedBy in JPA Bidirectional Relationships
Fast recall
Quick revision
Core answer
Whether you understand bidirectional ownership and how mappedBy stops JPA from duplicating the relationship in the schema
Omitting mappedBy in a bidirectional relationship, which produces duplicate foreign key columns or an extra join table
Explain that mappedBy tells Hibernate 'don't create a new column, just navigate through the FK that already lives on the other side'
Interview-ready guide
Interview answer
Suppose OrderItem has a field named order with @ManyToOne and @JoinColumn(name = "order_id"). Order can expose @OneToMany(mappedBy = "order") List
mappedBy in JPA Bidirectional Relationships
Direct Answer
mappedBy marks the inverse side of a bidirectional @OneToOne, @OneToMany, or @ManyToMany relationship. Its value is the Java attribute name on the owning entity, not a database column name. The owning side controls the relationship update; mappedBy tells JPA that both fields describe the same relationship.
Code Example
@Entity
class Order {
@Id @GeneratedValue private Long id;
private String orderNumber;
// Inverse side: mappedBy points to the 'order' field in OrderItem
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> items = new ArrayList<>();
// Helper keeps BOTH sides in sync in memory
public void addItem(OrderItem item) {
items.add(item);
item.setOrder(this); // set the owning side — this is what persists
}
}
@Entity
class OrderItem {
@Id @GeneratedValue private Long id;
private String productName;
private int quantity;
// Owning side: has @JoinColumn, controls the FK column
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", nullable = false)
private Order order;
public void setOrder(Order order) { this.order = order; }
}
// Without mappedBy, Hibernate would create BOTH:
// 1. order_item.order_id (from @ManyToOne)
// 2. an order_items join table (from @OneToMany)
Common Mistakes & Pitfalls
- Forgetting mappedBy entirely — the classic mistake; Hibernate creates a redundant join table plus the FK column, so the schema has two representations of one relationship.
- Typo in the mappedBy value — if Employee's field is
deptbut you writemappedBy = "department", Hibernate throws 'could not resolve property' at startup. It must match the Java field name, not the column name. - mappedBy on the wrong side — putting it on the @ManyToOne is ignored, because the @ManyToOne is always the owner by definition.
Check your understanding
Answer these without looking back at the article.
- What happens if you forget mappedBy?
- Which side should be the owning side?
- How do you maintain both sides of a bidirectional relationship?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.