Java.Hibernate.Medium.What is subselect fetching?

🔎 What is subselect fetching?

Subselect fetching is a Hibernate-specific fetch strategy for collections (e.g., @OneToMany, @ManyToMany) that reduces the N+1 select problem in a different way than batch or join fetches.

Instead of:

  • executing N separate queries (1 per parent) for each collection,
  • or doing a single join query that risks Cartesian products,

Hibernate with subselect will:
1️⃣ Load your list of parent entities (e.g., 20 authors).
2️⃣ When you access the collection on any one of those parents, Hibernate triggers one secondary query with a WHERE parent_id IN (...) subselect, fetching collections for all the parents in the original list.


🔎 Example:

1️⃣ Load authors:

SELECT * FROM authors LIMIT 20;

2️⃣ Later, you access author.getBooks() on any of those 20 authors → Hibernate issues a single subselect:

SELECT * FROM books WHERE author_id IN (1, 2, 3, ..., 20);

That one query populates the collections for all 20 authors → solving the N+1 problem.

How do you enable subselect fetching?

Use Hibernate’s @Fetch(FetchMode.SUBSELECT) annotation on your collection mapping:

@Entity
public class Author {
    @OneToMany(mappedBy = "author", fetch = FetchType.LAZY)
    @Fetch(FetchMode.SUBSELECT) // Hibernate-specific
    private List<Book> books;
}

How is it different from batch fetching?

  • Batch fetching groups proxies in fixed-size batches (e.g., 10), issuing multiple small queries as needed.
  • Subselect fetching triggers a single query with a subselect covering all parents loaded in the original query, loading all collections at once.

How is it different from join fetching?

  • Join fetch loads parents and collections in one big SQL query with a JOIN, but can cause duplicate parent rows (Cartesian explosion).
  • Subselect fetch loads collections in a separate single query, avoiding duplication and keeping parent query and collection query separate.

🚨 Caveats:

  • Subselect fetching only works if you load a collection of parents (e.g., List<Author>), not a single parent entity.
  • Large IN (...) lists (hundreds or thousands of IDs) may hurt performance or exceed database limits.

🔥 Summary:

Subselect fetching is a Hibernate strategy that issues one additional query with a WHERE parent_id IN (...) subselect, loading all collections for a set of parents in a single query and avoiding the classic N+1 problem.

This entry was posted in Без рубрики. Bookmark the permalink.