What is the N+1 SELECT problem in Hibernate? How can it be prevented?

The N+1 SELECT problem happens when Hibernate executes one query to fetch N parent rows, then lazily issues one additional query per parent to fetch each parent's associated child data — resulting in N+1 total queries instead of one or two.

Key Points: • It's most commonly triggered by default lazy-loaded @OneToMany or @ManyToOne associations accessed in a loop. • JOIN FETCH in HQL/JPQL retrieves the parent and its children in a single SQL query using a join. • @BatchSize groups the follow-up queries into batches (e.g. fetching children for 20 parents per query) instead of one per parent. • Subselect fetching (FetchMode.SUBSELECT) loads all children for the whole result set with one extra query. • Enabling SQL logging (show_sql / a tool like p6spy) is the standard way to spot N+1 problems during development.

Example: Fetching 100 Author entities and then looping over each to print author.getBooks() triggers 1 query for the authors plus 100 more for each author's books; adding JOIN FETCH b to the original query collapses that into a single SQL statement.

Code Example:

// N+1 prone
List<Author> authors = session.createQuery("from Author", Author.class).list();
authors.forEach(a -> a.getBooks().size()); // one query per author

// Fixed with JOIN FETCH
List<Author> authors = session.createQuery(
    "select distinct a from Author a join fetch a.books", Author.class).list();

Interview Tip: A concise interview answer is:

"The N+1 problem is when fetching N parents triggers N extra queries for their lazy associations. I prevent it with JOIN FETCH for cases I know I need eagerly, or @BatchSize / subselect fetching when I want to keep laziness but batch the follow-up queries, and I catch it early by watching the generated SQL."