Nel mio progetto Wicket + JPA/Hibernate + Spring, gran parte delle funzionalità si basa sulla pagina della posta in arrivo dove, utilizzando molte opzioni di filtro (non tutte devono essere utilizzate), gli utenti possono limitare il set di oggetti con cui vogliono lavorare. Mi stavo chiedendo quale sia la migliore strategia per implementare questo filtro? Nella vecchia versione di questa applicazione, la query di ricerca è stata creata concatenando stringhe contenenti condizioni SQL. Recentemente ho letto della nuova API Criteria fornita da JPA: consiglieresti di utilizzare questa funzione con la stringa di ricerca? E come si combina con il livello DAO? Non sta creando la query di ricerca utilizzando l'API Criteria nel livello aziendale una violazione della separazione dei livelli?Query di ricerca complesse JPA
risposta
Per il filtraggio di query come la descrizione, si consiglia di utilizzare l'API di criteri Hibernate o JPA a causa del supporto per le query condizionali. Di solito inserisco il codice di costruzione dei criteri nei DAO e trasmetto tutti gli argomenti necessari (eventualmente null).
Ecco un metodo DAO esempio da un'applicazione di autonoleggio esempio usando il criterio Hibernate API:
public List<VehicleRentalContract> list(Long contractID,
String customerNameOrID, Date date,
String vehicleDescriptionOrRegistration) {
Criteria criteria = getSession().createCriteria(
VehicleRentalContract.class);
// contractID filter
if (contractID != null && contractID != 0) {
criteria.add(Restrictions.eq("id", contractID));
}
// customerNameOrID filter
if (customerNameOrID != null && customerNameOrID.length() > 0) {
try {
Long customerID = Long.parseLong(customerNameOrID);
criteria.add(Restrictions.eq("customer.id", customerID));
} catch (NumberFormatException e) {
// assume we have a customer name
String customerNameQuery = "%" + customerNameOrID.trim() + "%";
criteria.createAlias("customer", "customer").add(
Restrictions.or(Restrictions.like("customer.firstName",
customerNameQuery), Restrictions.like(
"customer.lastName", customerNameQuery)));
}
}
// date filter
if (date != null) {
criteria.add(Restrictions.and(
Restrictions.le("rentalPeriod.startDate", date),
Restrictions.ge("rentalPeriod.endDate", date)));
}
// vehicleDescriptionOrRegistration filter
if (vehicleDescriptionOrRegistration != null
&& vehicleDescriptionOrRegistration.length() > 0) {
String registrationQuery = "%"
+ Vehicle
.normalizeRegistration(vehicleDescriptionOrRegistration)
+ "%";
String descriptionQuery = "%"
+ vehicleDescriptionOrRegistration.trim() + "%";
criteria.createAlias("vehicle", "vehicle").add(
Restrictions.or(Restrictions.like("vehicle.registration",
registrationQuery), Restrictions.like(
"vehicle.description", descriptionQuery)));
}
List<VehicleRentalContract> contracts = criteria.list();
return contracts;
}
La chiamata CREATEALIAS può essere utilizzata in cui si avrebbe bisogno di un join in SQL.
anche io preferisco utilizzare Criteri su HQL e SQL, per me la ragione sarà la modularità e anche le prestazioni, perché quando il progetto entra in produzione, il problema principale che dobbiamo affrontare sono le prestazioni, né HQL né SQL possono competere con Criteria su prestazione.
Aggiunta a sopra Il livello DAO viene creato per accedere ai dati e questo livello deve essere chiaro come il vetro senza alcuna codifica complessa o logica aziendale, ma in caso di criteri, si deve scrivere una logica (creare criteri) per arrivare a un modo migliore e sintonizzato per accedere all'oggetto, quindi, a mio modo di vedere, non c'è alcuna violazione nel mettere molta logica nel livello DAO.
Non penso che nessuna API di alto livello possa sovraperformare SQL, perché tutto finisce come query SQL dopo tutto. –
due approcci:
1 .. a seconda del tipo di filtraggio è necessario si può essere in grado di raggiungere questo obiettivo con la ricerca per esempio indicizzare tutti gli oggetti con Lucene e quindi utilizzare le query di ricerca per eseguire il filtraggio. ad esempio, costruire una query come:
titolo: "Il modo giusto" & mod_date: [20.020.101 20.030.101 TO]
See: http://lucene.apache.org/java/2_4_0/queryparsersyntax.html
2 .. O utilizzando criteri ...
userei il nuovo type-safe criteri api da hibernate:
Invece di un metodo che si accumula molto grandi criterio, mi piacerebbe provare a separare fuori tutta la logica utilizzando criteri indipendenti -
Con una combinazione di questi due si sarebbe in grado di costruire criteri facilmente.
Un altro luogo dove cercare ispirazione sono i cercatori dinamici dei graal. Questo è essenzialmente ciò che stai cercando di ottenere in modo statico.
http://www.grails.org/doc/1.0.x/guide/single.html#5.4.1 dinamici Finders
se si vuole veramente completa separazione degli strati si potrebbe implementare una semplice grammatica. Quindi analizzarlo per creare i criteri pertinenti. Ciò consentirebbe la modifica delle implementazioni dei criteri sottostanti. Se questo è appropriato dipende da quanto sia importante per te questa astrazione.
- 1. Sottostringa di ricerca JPQL (JPA)
- 2. Come passare query complesse in REST?
- 3. Query SQL per gestire relazioni complesse
- 4. Prestazioni ORM (specialmente NHibernate) per query complesse
- 5. JPA criteri di query distinti
- 6. Come creare stringhe di query Lucene più complesse?
- 7. Query JPA ricorsiva?
- 8. È possibile costruire query complesse contro DB noSQL
- 9. Tutorial criteri JPA
- 10. Modo elegante di eseguire query non elaborate complesse utilizzando ContentProvider
- 11. Query dinamica JPA 2.0 utilizzando l'API criteri
- 12. Proiezioni di sospensione complesse
- 13. Come ottimizzare un JPA Query
- 14. Primavera JPA Repository query dinamica
- 15. Hibernate Query Hint per JPA
- 16. Criteri lingua query JPA Costruttore
- 17. Unione di tabelle complesse
- 18. query di criteri Oracle in JPA
- 19. Ottimizzazione query di ricerca MySQL
- 20. PHP mysql query di ricerca
- 21. Come implementare query complesse con una API REST?
- 22. Consiglia un provider LINQ adatto (server SQL, query complesse)
- 23. JavaScript Interfaccia booleana di query di ricerca query costruttore booleano?
- 24. Come imporre LIMIT sulla sub-query della query JPA?
- 25. Come scrivere questa query utilizzando la query dei criteri JPA?
- 26. JPA Query su un tavolo unirsi
- 27. Java/JPA | Query con tipo ereditato specificato
- 28. TypedQuery anziché normale Query in JPA
- 29. Domande dinamiche complesse in CouchDB
- 30. Criteri JPA API di query e ordine di due colonne
+1 per il concetto di base. Sebbene si possa discutere sull'utilizzo del parametro customerNameOrID. Sembra annidare un "o" nei parametri altrimenti "e" -related. Questo può diventare arbitrariamente complesso se si verifica un caso in cui i tipi di dati sono uguali. In questi casi è probabilmente meglio creare sovraccarichi con set di parametri diversi. –
@Adriaan Koster L'elenco degli argomenti può essere sostituito da una classe che disegna la ricerca, ad esempio ** VehicleRentalContractCriteria ** –
@Martin 'customerNameOrID' viene da un campo di input di testo in cui l'utente può immettere una parte del cliente nome o un ID cliente. Non vedo come suggerisci di semplificare l'OR annidato, per favore mostraci. –