1. Información general
Querydsl es un amplio marco de trabajo de Java, que ayuda a crear y ejecutar consultas con seguridad de tipos en un lenguaje específico de dominio que es similar a SQL .
En este artículo exploraremos Querydsl con la API de persistencia de Java.
Una nota al margen rápida aquí es que HQL para Hibernate fue el primer idioma de destino para Querydsl, pero hoy en día es compatible con JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections y RDFBean como backends.
2. Preparativos
Primero agreguemos las dependencias necesarias en nuestro proyecto Maven:
2.5.0 com.querydsl querydsl-apt ${querydsl.version} provided com.querydsl querydsl-jpa ${querydsl.version} org.slf4j slf4j-log4j12 1.6.1
Y ahora configuremos el complemento APT de Maven:
... com.mysema.maven apt-maven-plugin 1.1.3 process target/generated-sources com.querydsl.apt.jpa.JPAAnnotationProcessor ...
El JPAAnnotationProcessor encontrará tipos de dominio con anotada javax.persistence.Entity anotación y genera tipos de consulta para ellos.
3. Consultas con Querydsl
Las consultas se construyen en función de los tipos de consultas generados que reflejan las propiedades de sus tipos de dominio. Además, las invocaciones de funciones / métodos se construyen de forma totalmente segura para los tipos.
Las rutas de consulta y las operaciones son las mismas en todas las implementaciones y también las interfaces de consulta tienen una interfaz base común.
3.1. Una entidad y el tipo de consulta Querydsl
Primero definamos una entidad simple que vamos a utilizar a medida que avanzamos en los ejemplos:
@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String firstname; @Column private String surname; Person() { } public Person(String firstname, String surname) { this.firstname = firstname; this.surname = surname; } // standard getters and setters }
Querydsl generará un tipo de consulta con el nombre simple QPerson en el mismo paquete que Person . QPerson se puede utilizar como una variable de tipo estático en consultas Querydsl como representante del tipo Person .
Primero: QPerson tiene una variable de instancia predeterminada a la que se puede acceder como un campo estático:
QPerson person = QPerson.person;
Alternativamente, puede definir sus propias variables de Persona como esta:
QPerson person = new QPerson("Erich", "Gamma");
3.2. Crear consulta con JPAQuery
Ahora podemos usar instancias de JPAQuery para nuestras consultas:
JPAQuery query = new JPAQuery(entityManager);
Tenga en cuenta que el entityManager es un EntityManager de JPA .
Ahora recuperemos todas las personas con el nombre " Kent " como ejemplo rápido:
QPerson person = QPerson.person; List persons = query.from(person).where(person.firstName.eq("Kent")).list(person);
La llamada from define el origen y la proyección de la consulta, la parte where define el filtro y la lista le dice a Querydsl que devuelva todos los elementos coincidentes.
También podemos utilizar varios filtros:
query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));
O:
query.from(person).where(person.firstName.eq("Kent").and(person.surname.eq("Beck")));
En formato JPQL nativo, la consulta se escribiría así:
select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"
Si desea combinar los filtros mediante "o", utilice el siguiente patrón:
query.from(person).where(person.firstName.eq("Kent").or(person.surname.eq("Beck")));
4. Orden y agregación en Querydsl
Veamos ahora cómo funcionan el orden y la agregación dentro de la biblioteca Querydsl.
4.1. Ordenar
Comenzaremos ordenando nuestros resultados en orden descendente por el campo de apellido :
QPerson person = QPerson.person; List persons = query.from(person) .where(person.firstname.eq(firstname)) .orderBy(person.surname.desc()) .list(person);
4.2. Agregación
Let's now use a simple aggregation, as we do have a few available (Sum, Avg, Max, Min):
QPerson person = QPerson.person; int maxAge = query.from(person).list(person.age.max()).get(0);
4.3. Aggregation With GroupBy
The com.mysema.query.group.GroupBy class provides aggregation functionality which we can use to aggregate query results in memory.
Here's a quick example where the result are returned as Map with firstname as the key and max age as the value:
QPerson person = QPerson.person; Map results = query.from(person).transform( GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));
5. Testing With Querydsl
Now, let's define a DAO implementation using Querydsl – and let's define the following search operation:
public List findPersonsByFirstnameQuerydsl(String firstname) { JPAQuery query = new JPAQuery(em); QPerson person = QPerson.person; return query.from(person).where(person.firstname.eq(firstname)).list(person); }
Y ahora construyamos algunas pruebas usando este nuevo DAO y usemos Querydsl para buscar objetos Person recién creados (implementados en la clase PersonDao ) y en otra agregación de prueba usando la clase GroupBy se prueba:
@Autowired private PersonDao personDao; @Test public void givenExistingPersons_whenFindingPersonByFirstName_thenFound() { personDao.save(new Person("Erich", "Gamma")); Person person = new Person("Kent", "Beck"); personDao.save(person); personDao.save(new Person("Ralph", "Johnson")); Person personFromDb = personDao.findPersonsByFirstnameQuerydsl("Kent").get(0); Assert.assertEquals(person.getId(), personFromDb.getId()); } @Test public void givenExistingPersons_whenFindingMaxAgeByName_thenFound() { personDao.save(new Person("Kent", "Gamma", 20)); personDao.save(new Person("Ralph", "Johnson", 35)); personDao.save(new Person("Kent", "Zivago", 30)); Map maxAge = personDao.findMaxAgeByName(); Assert.assertTrue(maxAge.size() == 2); Assert.assertSame(35, maxAge.get("Ralph")); Assert.assertSame(30, maxAge.get("Kent")); }
6. Conclusión
Este tutorial ilustró cómo construir un proyecto JPA usando Querydsl.
La implementación completa de este artículo se puede encontrar en el proyecto github: este es un proyecto maven basado en Eclipse, por lo que debería ser fácil de importar y ejecutar tal como está.
Una nota rápida aquí es: ejecute una compilación maven simple (instalación limpia de mvn) para generar los tipos en fuentes de destino / generadas , y luego, si está utilizando Eclipse, incluya la carpeta como una carpeta de origen del proyecto.