¿Qué es el problema N+1 en JPA y cómo se soluciona?
Opciones
- Significa que la base de datos tiene N+1 tablas en su esquema
- Una consulta para N padres, luego una por padre:
JOIN FETCH(Opción correcta) - Significa que la aplicación usa N+1 threads en total
- Es un error de sintaxis que JPQL reporta al arrancar
Respuesta
Una consulta carga N padres y luego una consulta extra por padre carga sus hijos (N+1 consultas en total). Se soluciona con JOIN FETCH, @EntityGraph o batch fetching
Por qué
Ejemplo: findAll() carga 100 usuarios (1 consulta). Luego tu código recorre la lista y llama a user.getOrders(), que es LAZY, así que JPA lanza 1 consulta por usuario: 100 más. Total 101 consultas en lugar de 1 o 2.
Soluciones: select u from User u join fetch u.orders carga todo con un JOIN; @EntityGraph(attributePaths = "orders") en el método del repository; @BatchSize para cargar hijos por grupos; o una proyección a DTO que seleccione solo lo necesario.
Se detecta activando el log de SQL y contando las consultas.
@Query("select u from User u join fetch u.orders")
List<User> findAllWithOrders();Recuerda
N+1 = 1 consulta de padres + 1 por hijo. Lo resuelve un fetch join.