Hibernate — Cheat Sheet

Tag: hibernate, jpa, orm, java, spring, sql

Livello: intermedio

TL;DR: Framework ORM per Java che mappa oggetti su tabelle relazionali. Semplifica le operazioni sul database riducendo drasticamente il boilerplate SQL.

Concetti chiave

-

Rappresenta l'implementazione più diffusa delle specifiche JPA (Java Persistence API).

-

Esegue il mapping relazionale a oggetti (ORM) tramite annotazioni come @Entity e @Table.

-

Usa Session e SessionFactory (o EntityManager in JPA) per la connessione.

-

Supporta HQL (Hibernate Query Language), un linguaggio simile a SQL ma orientato agli oggetti.

-

Implementa meccanismi di caching a due livelli per ottimizzare le letture al database.

-

Gestisce il caricamento delle relazioni tramite le strategie di fetch LAZY ed EAGER.

-

Genera automaticamente gli schemi del database (DDL) in base al modello a oggetti.

-

Mantiene traccia dei cambiamenti sugli oggetti persistenti tramite dirty checking automatico.

Domande tipiche e risposte pronte

-

Q: Qual è la differenza tra caricamento LAZY ed EAGER in Hibernate?R: Il LAZY carica i record relazionati solo quando chiamo il metodo getter, risparmiando memoria. L'EAGER li carica subito con la query principale usando una join.

-

Q: Cos'è il problema N+1 select e come lo previeni?R: Avviene quando si esegue una query per l'entità padre e poi N query per i figli. Lo risolvo forzando una JOIN FETCH in HQL o usando @EntityGraph.

-

Q: Come funzionano la cache di primo e secondo livello?R: La L1 è abilitata di default e legata alla singola Session. La L2 è opzionale, globale per tutta l'applicazione e richiede un provider esterno come Ehcache.

-

Q: Qual è la differenza tra un'entità in stato Detached e una in stato Transient?R: Un'entità Transient è appena istanziata e non ha ID né associazione al DB. Una Detached era salvata, ha un ID, ma la sua Session è stata chiusa.

Insidie e errori comuni

-

Usare FetchType.EAGER su relazioni @OneToMany o @ManyToMany, causando query massive e crolli di prestazioni.

-

Dimenticare l'annotazione @Transactional sui metodi di servizio, impedendo il commit delle modifiche nel database.

-

Abusare di HQL per query analitiche complesse, dove query SQL native o stored procedure risultano molto più efficienti.

-

Modificare un'entità Detached e aspettarsi che venga salvata senza riattaccarla esplicitamente con il metodo merge().

Snippet e comandi

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "email_address", nullable = false, unique = true)
    private String email;

    @OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Order> orders = new ArrayList<>();

    // costruttori, getter e setter omessi
}

Java

// Esempio HQL con JOIN FETCH per evitare N+1
String hql = "SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :userId";
User utente = entityManager.createQuery(hql, User.class)
                           .setParameter("userId", 1L)
                           .getSingleResult();

Da ripassare

-

[ ] Transizioni del ciclo di vita dell'entità (persist, merge, remove)

-

[ ] Integrazione tra Hibernate e Spring Data JPA

-

[ ] Differenze tra @GeneratedValue IDENTITY e SEQUENCE

Riferimenti

-

Documentazione ufficiale Hibernate ORM

-

Specifica Java Persistence API (JPA)

Jarvis Interviews
Jarvis