Interview Questions
JPA Interview Questions and Answers
JPA interviews test whether you can correctly model relationships between entities and reason about cascade/fetch behavior -- both frequent sources of real production bugs, not just trivia.
Example: Mapping a bidirectional one-to-many relationship
Java@Entity
public class Author {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Book> books = new ArrayList<>();
}
@Entity
public class Book {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "author_id")
private Author author; // Book is the owning side -- it holds the foreign key
}
Frequently Asked Questions
They describe the same relationship from opposite sides. In an Author-Book relationship, one author has many books (@OneToMany on Author) and each book belongs to one author (@ManyToOne on Book). The @ManyToOne side is conventionally the "owning" side, since that's where the foreign key column actually lives in the database.
It marks the non-owning side of a bidirectional relationship, telling JPA "this side doesn't own the foreign key -- look at this other field on the related entity for the actual mapping." Without it, JPA might try to create an unnecessary join table instead of using the existing foreign key column.
LAZY defers loading the related entity/collection until it's actually accessed. EAGER loads it immediately alongside the parent, every time. @ManyToOne and @OneToOne default to EAGER; @OneToMany and @ManyToMany default to LAZY. Defaulting most relationships to LAZY (overriding where genuinely needed) is the common recommendation, to avoid pulling in far more data than a given query actually needs.
It propagates every operation (persist, merge, remove, etc.) from the parent entity to its related entities -- saving an Author would also save its Books automatically, for example. It's risky on a @ManyToOne side, since saving a Book shouldn't accidentally also modify or delete its shared Author -- cascade should generally only be used where the child truly can't exist without the parent (an "ownership" relationship).
orphanRemoval = true deletes a child entity automatically when it's removed from its parent's collection (e.g. author.getBooks().remove(book)), even if you never explicitly call delete on that Book. CascadeType.REMOVE only deletes children when the parent entity itself is deleted -- it doesn't react to a child simply being removed from the collection.
JPQL (Java Persistence Query Language) queries against entity objects and their fields, not database tables and columns directly -- SELECT a FROM Author a WHERE a.name = :name, not SELECT * FROM author. JPA translates it into the appropriate SQL for your actual database at runtime, which is part of what keeps JPA code portable across different databases.
@Id marks the field that's the entity's primary key. @GeneratedValue tells JPA the database (or a sequence/table strategy) should generate that value automatically -- common strategies are IDENTITY (auto-increment column, common for MySQL/SQL Server), SEQUENCE (a database sequence object, common for PostgreSQL/Oracle), and AUTO (JPA picks based on the database).