Mapping and Relationships

What is the owning side of a relationship and what does mappedBy mean?

The owning side is the entity whose table holds the foreign key; only changes on the owning side are written to the database. The other side uses mappedBy to say "this is just a mirror of the field over there". In @OneToMany/@ManyToOne, the @ManyToOne side always owns.

@Entity
public class Order {
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items = new ArrayList<>();

    public void addItem(OrderItem item) {   // keep both sides in sync
        items.add(item);
        item.setOrder(this);
    }
}

@Entity
public class OrderItem {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")          // owning side: holds the FK
    private Order order;
}

Note: If you only do order.getItems().add(item) without item.setOrder(order), the order_id column is saved as NULL.

Unidirectional @OneToMany vs bidirectional: which is better?

A unidirectional @OneToMany without @JoinColumn creates an extra join table (orders_items) and produces extra INSERT/DELETE statements. With @JoinColumn it uses a FK but may still issue extra UPDATEs to set it.

The most efficient mapping is @ManyToOne on the child (often enough on its own) plus, if you need navigation from the parent, @OneToMany(mappedBy = ...).

@JoinColumn vs @JoinTable?

@JoinColumn names the foreign-key column in the owning table (order_items.order_id). @JoinTable describes a link table with two FKs; it is required for @ManyToMany and optional for others.

@ManyToMany
@JoinTable(name = "product_tags",
           joinColumns = @JoinColumn(name = "product_id"),
           inverseJoinColumns = @JoinColumn(name = "tag_id"))
private Set<Tag> tags = new HashSet<>();

What are the problems with @ManyToMany and how do you avoid them?

  • Use a Set, not a List: with a List (a "bag") Hibernate deletes all link rows and re-inserts them when one element is removed.
  • Never use CascadeType.REMOVE/ALL on it: deleting a product would delete shared tags.
  • If the link needs extra columns (quantity, added_at), replace it with a join entity and two @ManyToOnes, e.g. CartItem(user, product, quantity).

Explain cascade types. What is orphanRemoval and how is it different from CascadeType.REMOVE?

Cascade passes an operation from parent to child: PERSIST, MERGE, REMOVE, REFRESH, DETACH, or ALL. Use it on parent → child compositions (Order → OrderItem), not on @ManyToOne (an item must not delete its product).

CascadeType.REMOVEorphanRemoval = true
Parent deletedchildren deletedchildren deleted
Child removed from the collectionnothing happens (child row stays)child row is deleted

Inheritance mapping: SINGLE_TABLE vs JOINED vs TABLE_PER_CLASS vs @MappedSuperclass?

StrategyTablesPros / cons
SINGLE_TABLE (default)one table + discriminator columnfastest, no joins; subclass columns must be nullable
JOINEDparent table + one table per subclassnormalized, NOT NULL possible; joins on every read
TABLE_PER_CLASSone full table per concrete classpolymorphic queries need UNION; rarely used
@MappedSuperclassno table for the parentshares fields only (id, createdAt); cannot query the parent type

How should you map an enum, and what are embeddables?

Use @Enumerated(EnumType.STRING). The default ORDINAL stores 0, 1, 2..., so inserting a new constant in the middle silently corrupts existing data.

@Embeddable is a value object without its own identity or table; its fields are stored as columns of the owning entity (@Embedded Address address → street, city, pincode columns).

@Enumerated(EnumType.STRING)
private OrderStatus status;     // stored as 'PLACED', 'SHIPPED'

@Embedded
private Address shippingAddress;

What are the default fetch types for each association?

AnnotationDefault fetch
@ManyToOneEAGER
@OneToOneEAGER
@OneToManyLAZY
@ManyToManyLAZY
@ElementCollectionLAZY

Tip: Set fetch = FetchType.LAZY on every @ManyToOne and @OneToOne, then fetch what each use case needs explicitly.