You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Ci sono 5 tipi di query che permettono in diversi contesti di integrare JPQL nelle applicazioni Java:
Query Dinamiche: specificate a run-time (costose in termini di prestazioni)
Named Query: statiche, definite e non modificabili
Criteria API: un nuovo tipo di query object-oriented (>JPA 2.0)
Query Native: per eseguire SQL nativo invece di JPQL
-Tramite metodi dell'Entity Manager si ottiene una query di un certo tipo, dalla quale si vanno a prelevare risultato/risultati ecc.
Query API
Eseguire una query ed ottenere risultati
Settare parametri per una query
Ottenere parametri da una query
Query Dinamiche
Restituito un oggetto Query.
Il risultato della query è una lista
Il metodo getResultList() method restituisce una lista di Customer entities (List)
restituisce una lista di untyped objects.
Queryquery = em.createQuery("SELECT c FROM Customer c");
List<Customer> customers = query.getResultList();
Se invece vogliamo l'effetto paginazione:
Queryquery = em.createQuery("SELECT c FROM Customer c");
query.setMaxResults(10);
List<Customer> customers = query.getResultList();
Named Queries
Sono statiche e non modificabili
Meno flessibili ma più efficienti, dal momento che il persistence provider può tradurre la stringa JPQL in SQL una sola volta quando l'applicazione parte, e non ogni volta che la query deve essere eseguita.
@Entity@NamedQueries({
@NamedQuery(name = "findAll", query="select c from Customer c"),
@NamedQuery(name = "findVincent",
query="select c from Customer c where c.firstName = ’Vincent’"),
@NamedQuery(name = "findWithParam",
query="select c from Customer c where c.firstName = :fname")
})
publicclassCustomer {
@Id@GeneratedValueprivateLongid;
privateStringfirstName;
privateStringlastName;
privateIntegerage;
privateStringemail;
@OneToOne@JoinColumn(name = "address_fk")
privateAddressaddress;
// Constructors, getters, setters
Utilizzo:
Queryquery = em.createNamedQuery('findWithParam');
query.setParameter('fname', 'Vincent');
query.setMaxResults(3);
List<Customer> customers = query.getResultList();
// possiamo fare anche una cosa più fina, come:Queryquery = em.createNamedQuery("findWithParam").setParameter("fname","Vincent").setMaxResults(3);
Attenzione:
Essendo stringhe i parametri inseriti, eventuali errori dell'esecuzione delle query vengono riconosciuti a runtime
Ogni query deve possedere un nome univoco.
Criteria API (aka Object-Oriented-Queries)
Il vantaggio di scrivere concisamente le stringhe, è accoppiato al problema della mancanza di controlli a tempo di compilazione.
Errori come SLECT invece di SELECT sono scoperti a runtime.
Da JPA 2.0 ci sono le Criteria API, permettono di scrivere le query in maniera sintatticamente corretta.
L'idea è che tutte le keywords JPQL sono definite da questa API.
supporta tutto quello che può fare JPQL ma in maniera Object-Oriented.
SELECT, FROM, WHERE hanno un API representation attraverso i metodi: select() from() e where()
Native Queries
Prendono una native SQL statement (SELECT, UPDATE, DELETE...)
Tutte le query finora viste sono simili in comportamento
Le query stores sono invece esse stesse definite nel database
Utili per compiti ripetitivi ed ad alta intensità di uso dei dati.
Diversi vantaggi (anche se si perde di portabilità):
migliori prestazioni per la precompilazione
permette di raccogliere statistiche, per ottimizzare le prestazioni
evita di dover trasmettere dati (codice dal server)
codice centralizzato e usabile da diversi programmi (non solo java)
ulteriore possibilità di controlli di sicurezza (accesso alla stored procedure)
Esempio pratico
Servizio di archiviazione di libri e CD:
dopo una certa data, books e CDs devono essere archiviati.
fisicamente trasferiti dal magazzino al rivenditore
il servizio è time consuming e diverse tabelle vanno aggiornate.
inventory, warehouse, book, CD, transportation table...
Soluzione: scriviamo una stored-procedure che ragrgruppi diverse istruzioni SQL per migliorare le performance.
La stored procedure sp_archive_books
ha 2 argomenti in ingresso: archive date ed un warehouse code
aggiorna le tabelle T_inventory e T_transport
Procedura in SQL
Bad
CREATE PROCEDURE sp_archive_books @archiveDate DATE, @warehouseCode VARCHARASUPDATE T_Inventory
SET Number_Of_Books_Left -1WHERE Archive_Date < @archiveDate AND Warehouse_Code = @warehouseCode;
UPDATE T_Transport
SET Warehouse_To_Take_Books_From = @warehouseCode;
END
La stored procedure è compilata nel database e può essere invocata attraverso il suo nome sp_archive_books
La stored procedure accetta dati nella forma di parametri di input e di output (@archiveDate e @warehouseCode nel nostro esempio)
Ciclo di vita di un'entità
Per creare un'istanza della Customer entity, usiamo l'operatore new
Questo oggetto esiste in memoria anche se JPA non ne è ancora a conoscenza.
Se l'oggetto non viene usato, verrà liberato dal garbage collector ed il ciclo di vita termina.
Quando viene invocato il metodo EntityManager.persist() l'entità diventa managed ed il suo stato è sincronizzato col database.
in questa fase è possibile settare attributi:
customer.setFirstName() oppure fare il refresh del contenuto con il metodo EntityManager.refresh()
Tutti questi cambiamenti verranno sincronizzati col Database.
Possiamo anche eliminare il record con EntityManager.remove().
L'oggetto Java continuerà a risiedere in memoria fin quando non interverrà il Garbage Collector
Tipi di Callback
il ciclo di vita ha 2 stati:
persisting, updating, removing e loading.
Per ogn categoria, ci sono eventi pre ed eventi post che possono essere intercettati dall'entity manager quando si deve invocare un metodo di business.