En mi proyecto Wicket + JPA/Hibernate + Spring, gran parte de la funcionalidad se basa en la página Bandeja de entrada donde, utilizando muchas opciones de filtrado (no todas deben usarse), los usuarios pueden restringir el conjunto de objetos con los que quieren trabajar Me preguntaba cuál es la mejor estrategia para implementar este filtrado. En la versión anterior de esta aplicación, la consulta de búsqueda se construyó concatenando cadenas que contenían condiciones de SQL. Hace poco leí acerca de la nueva API de Criteria que proporciona JPA. ¿Lo recomendaría antes que trabajar con la cadena de búsqueda? ¿Y cómo se combina esto con la capa DAO? ¿No está construyendo la consulta de búsqueda utilizando Criteria API en la capa empresarial una brecha en la separación de capas?Consultas de búsqueda compleja JPA
Respuesta
Para filtrar consultas como las que describes, definitivamente recomiendo usar la API de criterios de Hibernate o JPA debido al soporte para consultas condicionales. Usualmente coloco el código de construcción de criterios en mi DAO y paso todos los argumentos requeridos (posiblemente nulos).
He aquí un método DAO ejemplo de una aplicación de alquiler de coches ejemplo utilizando el API de Hibernate criterios:
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 llamada createAlias se puede utilizar cuando se necesitaría una combinación en SQL.
incluso prefiero usar Criteria sobre HQL y SQL, para mí la modularidad y también el rendimiento, porque cuando el proyecto entra en producción, el principal problema al que nos enfrentamos es el rendimiento, ni HQL ni SQL pueden competir con Criteria actuación.
Añadiendo a la anterior La capa DAO se crea para acceder a los datos, y esta capa debe ser tan clara como el vidrio sin codificación compleja o lógica comercial, pero en caso de criterios, uno tiene que escribir una lógica (crear criterios) para llegar a una forma mejor y sintonizada de acceder al objeto, entonces, en mi opinión, no hay infracción al poner tanta lógica en la capa DAO.
No creo que una API de alto nivel pueda superar a SQL, ya que todo termina como consultas SQL después de todo. –
dos enfoques:
1 .. Dependiendo de qué tipo de filtrado que necesitan que usted puede ser capaz de lograr esto mediante la búsqueda, por ejemplo, indexe todos los objetos con Lucene y luego use consultas de búsqueda para realizar el filtrado. por ejemplo, construir una consulta como:
título: "La manera correcta" & mod_date: [20020101 A 20030101]
Ver: http://lucene.apache.org/java/2_4_0/queryparsersyntax.html
2 .. O usando criterios ...
que haría uso de un nuevo tipo de fallos criterios API de hibernación:
En lugar de un método que se acumula unas muy grandes criterios, que iba a tratar de separar toda la lógica utilizando criterios Independiente -
Con una combinación de estos dos sería capaz de construir subir los criterios fácilmente
Otro lugar para buscar inspiración son los buscadores dinámicos de grilles. Esto es esencialmente lo que estás tratando de lograr de una manera estática.
http://www.grails.org/doc/1.0.x/guide/single.html#5.4.1 dinámicos buscadores
Si realmente desea la completa separación de las capas se podía aplicar una gramática sencilla. Luego, analiza esto para crear los criterios relevantes. Esto permitiría cambiar las implementaciones de criterios subyacentes. Si esto es apropiado depende de cuán crucial es para usted esta abstracción.
- 1. Subcadena de búsqueda JPQL (JPA)
- 2. Cómo depurar consultas de JPA CriteriaBuilder
- 3. Una consulta compleja frente a consultas simples múltiples
- 4. JPA Nombrado Consultas vs Criterios API?
- 5. CAML caso de consultas de búsqueda sensible
- 6. Consultas de búsqueda de PHP mysql
- 7. Análisis de consultas de búsqueda en Java
- 8. TF * IDF para consultas de búsqueda
- 9. Consultas complejas con el constructor de criterios de JPA
- 10. Creación de consultas utilizando Criteria API (JPA 2.0)
- 11. JPA ¿Optimización de consultas al evitar JOIN para buscar tabla?
- 12. Resumen de consultas con nombre en un resumen JPA DAO
- 13. hibernate jpa criteriabuilder ignorar las consultas de casos
- 14. Tutorial de Criterios JPA
- 15. Mongo clasificación compleja?
- 16. compleja consulta LINQ
- 17. Pregunta compleja de wolframalpha ajax
- 18. JPA - Criterios de consulta - Búsqueda de enteros usando "como"
- 19. Las consultas nativas JPA/Hibernate no reconocen los parámetros
- 20. Depuración de consultas de búsqueda de Solr en Sunspot
- 21. cómo crear un analizador de consultas de búsqueda
- 22. RavenDB: Cómo realizar consultas con varios términos de búsqueda
- 23. Yii - Manipulación de consultas para CGridView personalizado con búsqueda avanzada
- 24. API de búsqueda web que permite consultas automatizadas
- 25. usando comodines en filtros/consultas de búsqueda LDAP
- 26. compleja consulta de combinación
- 27. Asociación compleja de consulta de DataMapper
- 28. ¿Por qué en las consultas de JPA EntityManager arroja NoResultException pero no encuentra?
- 29. Encuadernación compleja en bash
- 30. Pregunta demasiado compleja
+1 por concepto básico. Aunque uno podría discutir sobre el uso del parámetro customerNameOrID. Parece anidar un "o" en los parámetros de lo contrario "y" relacionados ". Esto puede volverse arbitrariamente complejo si surge un caso cuando los tipos de datos son iguales. Para estos casos, probablemente sea mejor crear sobrecargas con diferentes conjuntos de parámetros. –
@Adriaan Koster Su lista de argumentos puede ser reemplazada por una clase que dibuje su búsqueda, como ** VehicleRentalContractCriteria ** –
@Martin 'customerNameOrID' proviene de un campo de entrada de texto en el que el usuario puede ingresar una parte del cliente nombre, o una identificación de cliente. No veo cómo sugieres que simplifiques el OR anidado, muéstranoslo. –