2011-04-03 20 views
7

Uso le query HQL in Hibernate, e mi sono semplicemente chiesto se potevo aumentare le prestazioni della mia app riutilizzando le query.Riutilizzo di query in Hibernate

Di solito è necessario creare un nuovo oggetto di query per ogni sessione:

Session session; 
Query q1 = session.createQuery("select a from Article a where id=:id"); 
q1.setInteger("id",123); 
List result = q1.list(); 

ora ho query relativamente complesse in HQL, che io non voglio avere analizzato più e più volte. C'è un modo per creare una query e riutilizzarla in un'altra sessione? Come questo:

Session session; 
Query q2 = q1.reattach(); 
q2.setInteger("id",123); 
List result = q2.list(); 

Se Hibernate usa istruzioni preparate in ogni caso, questo dovrebbe essere un guadagno di prestazioni notevoli, soprattutto in combinazione con un ConnectionPool che memorizza nella cache istruzioni preparate.

EDIT: il riutilizzo di query in modalità di sospensione non è in genere necessario, poiché il piano di query è già memorizzato nella classe QueryPlanCache. Anche le Query nominate non forniscono alcun miglioramento, perché sono usate solo per cercare la stringa di query e nessun piano è associato a loro.

Per concludere: non è utile riutilizzare le query in sospensione. Assicurati solo di utilizzare le query parametrizzate SEMPRE, quindi mantieni le cache del piano piccole.

+0

@allingeek: su cosa esattamente? Basta aprire QueryPlanCache dalla sorgente di Hibernate. O cosa intendevi? – Daniel

+0

Quello che stavo veramente cercando era il riutilizzo di PreparedStatement. Inseguito la configurazione della cache dell'istruzione in c3p0 in base alla tua domanda e salvato il giorno. Grazie. – allingeek

risposta

4

È possibile utilizzare 'query denominata': Annotate la classe Entity come

@Entity 
@NamedQuery(name="Article.findById", query="select a from Article a where id=:id")  
public class Article{ ... 

e poi verrà analizzato una volta all'avvio, ogni volta che si desidera utilizzarlo si chiama semplicemente:

session.getNamedQuery("Article.findById") 
     .setInteger("id",123); 
+1

Accettato, anche se inutile :). Vedi la mia modifica alla mia domanda. – Daniel

0

Named Query come described by Kiavash fa quello che stai chiedendo ma dubito che ti dia qualche tipo di significativo aumento delle prestazioni.

Le istruzioni preparate vengono utilizzate se il database li supporta indipendentemente dal fatto che si stiano utilizzando o meno le query con nome di Hibernate. Al massimo si risparmia il problema di analizzare la query HQL. Named Query è più destinato al riutilizzo del codice.

+1

Questa era esattamente la mia intenzione. Uso già le istruzioni preparate nel database e so che gran parte del tempo rimanente della CPU è dedicato all'HQL della query. – Daniel