Pollito Blog
November 25, 2024

Let's talk Java: Data persistence en Spring

Posted on November 25, 2024  •  5 minutes  • 887 words  • Other languages:  English

¿Quién hace qué?

Hibernate

JPA

Spring Data JPA

Entonces… ¿Quién hace qué?

Spring Boot con JPA

La dependencia spring-boot-starter-data-jpa hace mucho trabajo pesado, pero hay algunas otras cosas que deberá considerar para que su proyecto Spring Boot con JPA e Hibernate funcione sin problemas.

  1. Dependencia de la base de datos: Necesita un controlador de base de datos (H2, MySQL, PostgreSQL, etc.). Spring Boot seleccionará automáticamente el controlador y configurará Hibernate para el dialecto apropiado según su base de datos.
  2. Debe configurar su conexión de base de datos y algunas propiedades JPA en application.properties (o application.yml).
  3. Clases de entidad.
  4. Interfaces de repositorio: Deberá crear una interfaz de repositorio que extienda las interfaces de Spring Data, como JpaRepository.

¿Necesita algo más?

¿Qué pasa con Eager/Lazy loading?

¿Cuál es la diferencia?

Aspecto Lazy Loading Eager Loading
Definición Los datos asociados se cargan solo cuando se accede a ellos. Los datos asociados se cargan inmediatamente con la entidad principal.
Ventajas Ahorra memoria al no cargar datos innecesarios. Simplifica el acceso a datos relacionados sin preocuparse por los límites de sesión/transacción.
Desventajas - Requiere una sesión de Hibernate activa; el acceso externo a resultados en LazyInitializationException. - Puede provocar un problema N+1 si se administra mal. - Carga datos innecesarios, lo que potencialmente desperdicia memoria y tiempo de procesamiento. - Puede generar consultas grandes y complejas que ralentizan el rendimiento.
Caso de uso Ideal para escenarios en los que no siempre se necesitan datos relacionados. Ideal para escenarios en los que siempre se requieren datos relacionados.
Hibernación predeterminada LAZY: para @OneToMany y @ManyToMany. EAGER: para @ManyToOne y @OneToOne.

¿Quién es responsable de Eager/Lazy Loading?

Problemas comunes y cómo solucionarlos

LazyInitializationException

@Transactional
public List<Post> getUserPosts(Long userId) {
    User user = userRepository.findById(userId).orElseThrow();
    return user.getPosts(); // Access within transaction
}

Problema N+1

@Query("SELECT u FROM User u JOIN FETCH u.posts WHERE u.id = :id")
Optional<User> findUserWithPosts(@Param("id") Long id);
@EntityGraph(attributePaths = {"posts"})
Optional<User> findById(Long id);

Sobrecarga con Eager Loading

Mejores prácticas

  1. Predeterminado en Lazy: Use FetchType.LAZY a menos que esté absolutamente seguro de que los datos siempre serán necesarios.
  2. Ámbito transaccional: Asegúrese de que se acceda a los datos cargados de forma diferida dentro de una transacción activa.
  3. Optimice las consultas: Use JOIN FETCH o EntityGraph para casos de uso específicos que requieran datos asociados.
  4. Perfil y monitor: Use herramientas como el registro SQL de Hibernate o el metamodelo JPA para monitorear qué consultas se están ejecutando.
  5. Evite obtener colecciones grandes: Para relaciones @OneToMany o similares, pagine los resultados cuando sea posible.
Hey, check me out!

You can find me here