Criteria API di Hibernate

Esaminiamo la Hibernate Criteria API, una potente ed elegante alternativa a HQL, ottima per funzionalità di ricerca dinamica dove Hibernate deve generare query complesse al volo

Funzionalità di ricerca con diversi criteri

Le funzionalità che richiedono complessi e molteplici criteri di ricerca sono presenti frequentemente nelle applicazioni nelle applicazioni web. Pagine con ricerche multicriterio hanno di solito un grande numero di parametri, molti dei quali opzionali. Ricerche di questo tipo sono quelle che troviamo in siti come eBayYahoo e Google.

Dove sono appropriate le ricerche con molteplici criteri?

In molti siti web pubblici le funzionalità di ricerca con criteri multipli tendono ad essere meno frequenti, anche perchè il più delle volte potrebbe bastare una ricerca testuale semplice o semplicemente non vengono utilizzate. Questo dipende poi dalla tipologia di sito, ad esempio su siti pubblici di prenotazione viaggi le ricerche avanzate vengono utilizzate per default. Per quanto riguarda siti web di business (privati, lan etc. etc.), trattandosi di una tipologia diversa di applicazioni, il più delle volte questa è una funzionalità che viene richiesta

L’approccio tradizionale

L’approccio tradizionale che viene utilizzato per implementare una query di ricerca con diversi criteri, attraverso Hibernate, richiede la costruzione di una query HQL al volo basata sui criteri di ricerca che vengono inseriti dall’utente. Viene qui riportato un esempio di questo approccio

Quest’approccio è prolisso e porta facilmente a degli errori. E’ anche rischioso nel contesto di un team di sviluppo, perchè sviluppatori inesperti potrebbero utilizzare pericolose scorciatoie seguendo questo pattern. Durante la revisione del codice mi è capitato di vedere molte volte di vedere funzioni per ricerche di questo tipo, dove erano presenti concatenazioni di stringhe, uso diretto dei parametri nella stringa della query e cosi via:

Come vedremo, la Hibernate Criteria API fornisce un metodo più sicuro e pulito per risolvere questo tipo di problemi

Utilizzare Hibernate Criteria API

L’API Criteria di Hibernate fornisce una maniera elegante per costruire query dinamiche al volo. Utilizzando questa tecnica, le 24 linee di codice dell’esempio precedente possono essere codificate in maniera più concisa e più chiaramente usando solo 8 linee di codice:

Vediamo ora con più dettaglio come utilizzare la Criteria API

Creare ed utilizzare l’oggetto Criteria di Hibernate

Un oggetto Criteria viene creato utilizzando il metodo createCriteria() di Session

Una volta creato è possibile aggiungere gli oggetti Criterion (generalmente ottenuti dai metodi statici della classe Expression) per costruire la query. I metodi come setFirstResult(), setMaxResults() e setCacheable() possono essere utilizzati per definire il comportamento della query, nello stesso modo in cui viene definito sull’oggetto Query utilizzando HQL. Alla fine per eseguire la query deve essere richiamato il metodo list() (oppure uniqueResult() se pensiamo di ottenere un solo risultato) :

Expression

La Criteria API supporta un vasto insieme di operatori per il confronto. Gli operatori standard SQL (=,,>=) sono supportati rispettivamente dai seguenti metodi della classe Expression: eq(), lt(), le(), gt() e ge()

Notate che come in HQL e a differenza delle query basate su JDBC, siete liberi di utilizzati gli oggetti business come parametri delle query, senza avere il bisogno di utilizzare riferimenti a chiavi primarie e foreign key. L’API fornisce inoltre dei comparatori aggiuntivi: like, between, in, isNull, isNotNull

Oltre a questo l’API fornisce operatori utili come: eqProperty, ltProperty etc.

Ordinare i risultati

In HQL (e in SQL), la clausola “order by” ci permette di ordinare i risultati delle query. Utilizzando l’API, questo lavoro viene svolto dal metodo addOrder() di Criteria e dalla classe Order

Join tra tabelle

Quando scriviamo query HQL, le clausole di join sono necessarie per ottimizzare la query utilizzando una clausola “left join fetch”, come nel seguente esempio (a questo proposito c’è un altro articolo sull’ottimizzazione)

Quando utilizziamo la Criteria API, possiamo fare la stessa cosa utilizzando il metodo setFetchMode()

Immaginate il caso di un negozio online che vende magliette. Ogni modello ha un certo numero di magliette con differenti taglie. Voi volete fare una query per trovare tutti i modelli di magliette con taglia superiore al 40. In HQL la query sarebbe stata la seguente

Utilizzando la Criteria API, potete usare createCriteria() per creare una inner join tra le due tabelle, come nel seguente esempio

Un altro modo per fare ciò è quello di utilizzare il metodo createAlias(), che non coinvolge una nuova istanza della classe Criteria

Notate che in entrambi i casi la collezione availableSizes in ogni oggetto Shirt non è stata inizializzata: è semplicemente usata come parte dei criteri di ricerca.

Quando i Criteria non sono appropriati

Come potete vedere la Hibernate Criteria API è senza dubbio fatta apposta per la generazione di query dinamiche. Tuttavia ci sono diverse situazioni in cui non è appropriata e magari complica il codice che è più complesso e difficile da manutenere rispetto alle query in HQL. Se la query che deve essere eseguita non richiede una costruzione dinamica allora l’uso di questa API probabilmente non è appropriato. Quando è possibile, esternalizzare delle query rappresenta un certo numero di vantaggi:

  • Query esternalizzate possono essere controllate ed ottimizzate da un DBA se necessario
  • Query inserite nei file di mapping di Hibernate sono più facili da manutenere rispetto a quelle inserite nel codice Java
  • Le query “named” di Hibernate sono più facili da inserire in una cache se necessario

 

Conclusioni

Hibernate Criteria è una potente ed elegante API, adatta per implementare funzionalità di ricerca basate su diversi criteri, quando le query di Hibernate devono essere costruite a runtime. Utilizzarla nelle giuste circostanze potrà dare come risultato un codice più pulito, più chiaro, più affidabile e manutenibile.

Articolo originale
Discuti l’articolo con l’autore John Ferguson Smart
Blog dell’autore John Ferguson Smart
Traduzione a cura di Federico Paparoni

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *