Queries Dinámicos en Spring Data JPA

Tuve la necesidad de crear un Query de forma dinámica con JPA, pues tenía varios métodos definidos y podrían crecer mas, algo así:

QuestionRepository.groovy
 

Inclusive se tienen que hacer consultas sobre relaciones de la misma clase. Es aquí en dónde la documentación de Spring ayuda diciéndonos al respecto de Specifications()

Describo lo que hice de manera genérica:

Uso de la interface JpaSpecificationExecutor

Sólo implementa la interface sobre el Repository que ya tengas definido:

QuestionRepository.groovy
 

Implementa el metamodelo

Te recomiendo que explores el paquete javax.persistence.metamodel, y la documentación de Hibernate para comprender mucho mejor de que trata la generación del metamodelo; en breve, te muestro un ejemplo que denota cuándo tienes atributos simples, una relación con un objeto o con una lista de objetos, lo cuçal funciona para poder buscar a través de ellos, justo como HQL o JPQL.

Question_.groovy
 

Observa que el metamodelo hace referencia a la clase original mapeada con @Entity, y que por convención se le suma un guión bajo en el nombre.

Crea el Criterion Spec

Aquí es dónde aplicaremos el _dinamismo_ de la consulta pues en base a un mapa descartaremos la estructura del query:

QuestionCriteriaSpecs.groovy
 

Aquí hay varias observaciones:

  • Se hace la implementación de la interface Specification, pero cómo estamos usando Groovy podemos hacerlo con un Closure, sin embargo, podrías hacerlo igual con Java y alguna Lambda.
  • Root usa el Metamodelo definido, query y builder son los que te ayudarán a crear tu búsqueda.
  • Revisá la documentación de cada clase, es muy recomendable.

Sólo úsalo...

Podemos sustituir todas las consultas anteriores por algo cómo lo siguiente:

 

Sólo es cuestión de manejar un Map y agregar los atributos por los cuáles quiero buscar

En resumen podría decirse que traslade complejidad pero dando un poco más de flexibilidad y re-uso.