- PERSIST, MERGE, REMOVE, REFRESH, DETACH.
Fetch →Controlla quando viene caricata la relazione:
- EAGER: caricamento immediato. 51
- LAZY: caricamento solo quando necessario (più efficiente ma più complesso).
Gestione delle Relazioni (Relationship Management)
JPA gestisce le relazioni usando chiavi esterne. Possiamo personalizzarle:
- @JoinColumn: per relazioni 1:1 e N:1.
o name: nome della colonna.
o referencedColumnName: nome della colonna nell’altra tabella.
o nullable, unique, insertable, updatable.
- @JoinTable: per relazioni N:N, con parametri simili.
Il lato proprietario (owning) è quello che contiene la foreign key. Il lato inverso è quello che fa riferimento al
proprietario con mappedBy.
Le associazioni in ORM possono essere unidirezionali o bidirezionali:
- Unidirezionale: solo un lato “vede” la relazione.
- Bidirezionale: entrambi i lati la conoscono.
Tipi di relazioni
Ogni tipo di relazione ha una propria annotazione:
→
- @OneToOne relazione uno-a-uno.Serve @JoinColumn sul lato proprietario per indicare la chiave esterna.
L’altro lato usa mappedBy. Parametri: cascade, fetch, mappedBy, optional, orphanRemoval.
→
- @ManyToOne Più entità fanno riferimento a una sola. Richiede @JoinColumn per specificare la chiave
esterna. Parametri: cascade, fetch, optional.
→
- @OneToMany Un’entità ha una lista di entità collegate. Non serve @JoinColumn (la chiave è nell’entità
“many”). Si usa mappedBy per dire da quale campo è gestita la relazione. Parametri: cascade, fetch,
orphanRemoval. →
- @ManyToMany Serve una tabella di collegamento. Si usa @JoinTable per specificare:
o name: nome della tabella
o joinColumns: chiavi esterne della propria entità.
o inverseJoinColumns: chiavi dell’altra entità.
Parametri: cascade, fetch.
Tipo di Annotazione Chiave esterna mappedBy @JoinTa Parametri principali Note
Relazione principale ble
@OneToOne cascade, fetch, Relazione simmetrica; uno
❌
↔ con sull’altro
♂️ ♂️ ✅ ✅
@JoinColumn optional, dei due gestisce
OneToOne lato orphanRemoval
sul lato
proprietario
@ManyToOn cascade, fetch, È sempre il lato
❌ ❌
→ con
♂️ ✅
e optional
@JoinColumn proprietario
ManyToOne @OneToMan cascade, fetch, Si usa in combinazione con
✅ ❌
→ (è nell’entità
♂️ ❌
y(mappedB @ManyToOne
orphanRemoval
OneToMany “many”)
y)
@ManyToMa cascade, fetch Serve tabella ponte con
✅
↔ tramite sull’altro
✅ ✅
ny @JoinTable joinColumns e
ManyToMany lato inverseJoinColumns
(opzionale)
Strategie di Caricamento (Loading Strategies)
Due approcci per gestire l’accesso ai dati relazionati: →
- Lazy Loading: i dati collegati sono caricati solo quando servono. relazione a cui si accede poche volte
o Vantaggi: meno dati caricati all’inizio.
o Svantaggi: più query successive.
→ evitare lazy loading con entità scollegate
→
- Eager Loading: i dati collegati sono caricati subito relazione navigata molto frequentemente
o Vantaggi: meno query nel tempo.
o Svantaggi: possibili sprechi se i dati non servono.
52
Alcuni ORM (come Hibernate) possono creare o aggiornare automaticamente lo schema del database in base alle entità.
Politiche comuni:
- Create: crea lo schema se non esiste.
- Drop-and-Create: cancella e ricrea lo schema ad ogni esecuzione (utile per test).
- Update: aggiorna lo schema per riflettere i cambiamenti nelle entità.
- Validate: controlla solo che schema e entità siano allineati.
- None: nessuna azione.
Querying
Quando usiamo un ORM (Object-Relational Mapping), come Hibernate o EclipseLink, non dobbiamo scrivere codice SQL
direttamente per parlare con il database. Al contrario, interagiamo tramite oggetti Java, e l’ORM si occupa di convertire
le operazioni in SQL.
Tipi di quey: →
- JPQL (Java Persistence Query Language) È simile a SQL ma lavora con entità e attributi, non con tabelle e
colonne. Le query JPQL sono portabili tra database (il provider JPA le traduce in SQL). Supporta SELECT,
UPDATE, DELETE (ma non INSERT, che si fa con persist()).
SELECT u FROM User u WHERE u.age > 18
Esempio:
Operatori supportati:
o Confronto: =, <>, <, >, <=, >=
o Logici: AND, OR, NOT
o Pattern: LIKE ‘%valore%’
o Insiemi: IN (‘A’, ‘B’)
o Range: BETWEEN 10 AND 20
o Null check: IS NULL, IS NOT NULL
Supporta due tipi di parametri, che permettono di assegnare valori dinamicamente a runtime invece di scriverli
direttamente nella query (hardcoding):
o Posizionali (?1, ?2) → si assegnano con setParameter(1, valore).
Query query = em.createQuery(“SELECT u FROM User u WHERE u.age >
?1 AND u.name = ?2”);
query.setParameter(1, 30);
query.setParameter(2, “Bob”);
→ In questo caso, i parametri vengono identificati tramite posizione numerica (1, 2, …).
o Nominali (:nome) → più leggibili, si assegnano con setParameter(“nome”, valore).
TypedQuery<User> query = em.createQuery(“SELECT u FROM User u WHERE
u.age > :age”, User.class);
query.setParameter(“age”, 25);
→ Qui, i parametri sono identificati tramite nome preceduto da due punti, rendendo la query più leggibile e
mantenibile.
- Named queries→ Sono query predefinite, scritte una volta dentro le entità e poi riutilizzabili ovunque. Sono
più veloci perché compilate una sola volta. Centralizzano le query nel codice, rendendolo più ordinato.
Esempio:
@Entity
@NamedQueries({
@NamedQuery{(name = "User.findMinors", query = "SELECT u FROM User u
WHERE u.age < 18"),
@NamedQuery…
)} 53
- Criteria API→ Serve a costruire query dinamiche in modo sicuro (type-safe, cioè controllato a livello di
compilazione) e flessibile. Invece di scrivere la query come stringa, la componiamo con oggetti Java. Utile
quando le condizioni cambiano a runtime.
Si parte da una CriteriaBuilder, che si ottiene dall’EntityManager. Con CriteriaBuilder.createQuery(Class<T>)
si crea una CriteriaQuery, che rappresenta la struttura della query. La query si costruisce specificando:
o Da quale entità leggere (Root<T>)
o Quali dati selezionare (con .select(…))
o Le condizioni di filtro (con .where(…))
→
Cb.equal(x,y) x = y
x>y
→
Cb.greaterThan(x,y)
→x<=y
cb.lessThanOrEqualTo(x, y)
cb.like(x, "Mario%")→x LIKE "Mario%"
x BETWEEN a AND b
→
cb.between(x, a, b)
x is NULL
→
cb.isNull(x)
cb.and(...), cb.or(...)→ combinazioni logiche
o Ordinamenti, raggruppamenti, condizioni having, ecc.
Una volta completata la CriteriaQuery, si converte in TypedQuery tramite EntityManager.createQuery(…) e poi
si esegue con getResultList().
È possibile usare parametri (ParameterExpression<T>) per evitare SQL injection e riutilizzare query. Si legano i
parametri prima dell’esecuzione usando .setParameter(…) su un TypedQuery.
Esempio:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> root = cq.from(User.class);
ParameterExpression<Integer> ageParam = cb.parameter(Integer.class,
“age”);
cq.select(root)
.where(cb.greaterThan(root.get(“age”), ageParam))
.orderBy(cb.asc(root.get(“name”)));
TypedQuery<User> query = entityManager.createQuery(cq);
query.setParameter(ageParam, 25);
List<User> results = query.getResultList();
Altri tipi speciali di query:
- CriteriaUpdate<T> per aggiornamenti massivi (più righe con una sola query)
- CriteriaDelete<T> per cancellazioni massicce
Esempio:
CriteriaUpdate<User> update = cb.createCriteriaUpdate(User.class);
Root<User> root = update.from(User.class);
update.set("status", "ACTIVE").where(cb.lessThan(root.get("age"),
18));
entityManager.createQuery(update).executeUpdate();
→
- Query Native (SQL puro) Se proprio abbiamo bisogno di funzioni particolari del database o massime
performance, possiamo scrivere query SQL classiche:
Query q = em.createNativeQuery("SELECT * FROM users WHERE age > 30");
Esempio:
Oggetto Query
La classe Query in JPA è l’interfaccia principale per eseguire query:
- È creata tramite l’EntityManager. 54
- Può essere di tipo generico o TypedQuery<T> (più sicura perché conosce il tipo di ritorno).
- Può eseguire query di tipo JPQL, Named o Native.
Tipi di creazione:
- createQuery(String qlString): crea una query JPQL.
- createNamedQuery(String name): usa una query predefinita (per NamedQuery)
- createNativeQuery(String sqlString): SQL puro.
- createQuery(String qlString, Class<T>): crea una TypedQuery (con tipo di ritorno specificato).
Configurazione delle Query
Prima di eseguire una query, puoi personalizzarla:
- Puoi passare parametri per evitare SQL hardcoded:
o setParameter(String name, Object value) → con nome.
o setParameter(int position, Object value) → posizionale.
o Per le date si usa anche TemporalType (DATE, TIME, TIMESTAMP).
Esecuzione delle Query
Una volta configurata la query, puoi eseguirla con:
- getResultList(): ritorna più risultati in una lista.
- getResultStream(): simile a sopra, ma come Stream.
- getSingleResult(): un solo risultato.
- executeUpdate(): per query UPDATE o DELETE, ritorna il numero di righe modificate.
Tipi di risultato
Il tipo di risultato dipende dalla query:
- TypedQuery<T> → restituisce oggetti di tipo T.
- Query generica → ritorna Object o Object[] (es. quando si selezionano più campi).
- Funzioni aggregate come COUNT, SUM → restituiscono un Number (da castare se necessario).
Per migliorare le performance:
- Paginazione: limita i risultati
o setMaxResults(int max) → massimo numero di risultati.
o setFirstResult(int start) → offset iniziale.
- JOIN FETCH: per evitare il problema N+1 (troppe query)
- Cache: per non rifare query inutili
- Indici sul database: per accessi rapidi
ORM – Sessions & Transactions
Una sessione, detta anche persistence context, è un ambiente temporaneo gestito dall’ORM (es. Hibernate),
in cui tiene traccia delle modifiche e può sincronizzarle con il DB in automatico. Durante la sessione:
- Gli oggetti caricati o
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
-
Programmazione a Oggetti [Java], Base e Avanzata - Ing. Informatica, Appunti di Programmazione Java
-
Appunti Programmazione ad oggetti e Java
-
Appunti di Programmazione orientata agli oggetti e Java
-
Appunti di Programmazione ad oggetti