If you’ve ever used the JPA criteria API, you probably know its drawbacks:
- less readable
- very verbose
- very ugly
Fortunately since some time there is QueryDSL around, which targets to solve this pain. QueryDSL is a framework that provides you with a simple and fluent api as an alternative to the JPA criteria api. Besides this, it’s still type-safe and very simple to use.
Examples
Ok, just let’s go through a simple example. Let’s assume we have the following person 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;
}
//getter & setter
...
}
If we want to find persons by their firstname with the JPA criteria API the query would look something like this:
CriteriaBuilder queryBuilder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteriaQuery = queryBuilder.createQuery(Person.class);
Root<Person> rootQuery = criteriaQuery.from(Person.class);
CriteriaQuery<Person> select = criteriaQuery.select(rootQuery);
Predicate p = queryBuilder.equal(rootQuery.get(Person_.firstname), firstname);
select.where(p);
TypedQuery<Person> typedQuery = em.createQuery(criteriaQuery);
return typedQuery.getResultList();
}
Not very intuitive, right? Try to remember that piece of code after one week not using the criteria api. It’s just a nightmare. It’s getting worse if you work with joins…
Ok, but now let’s have a look at the same query written with QueryDSL.
JPAQuery query = new JPAQuery(em);
QPerson person = QPerson.person;
return query.from(person).where(person.firstname.eq(firstname)).list(person);
}
That’s all? Yeah, it’s much much better than the JPA criteria API. Very simple, intuitive and easy to remind.
How can I add QueryDSL to my project?
I assume, that you’re using maven to build your project. To use QueryDSL, you have to add the QueryDSL dependencies to your pom.xml:
<dependencies>
<!-- QueryDSL -->
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-core</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>2.5.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
In addition to that, you have to add a maven plugin to your pom.xml to allow QueryDSL to generate some meta-classes for you (that are the classes with the Q-prefix).
<build>
...
<plugins>
<!-- QueryDSL plugin -->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>maven-apt-plugin</artifactId>
<version>1.0.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/metamodel</outputDirectory>
<processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
After that, you can let the maven plugin compile the meta-classes which occurs during the default maven compile process:
Conclusion
Now you can use QueryDSL to create some fancy simple sql queries. QueryDSL offers some more, like filtering lists and so on. For further information please have a look at the QueryDSL documentation.
Source-Code
You can find a full working example at GitHub.
2 Comments
Hi Christian,
A nice blog post. Just to nitpick a bit it is spelled Querydsl not QueryDSL 🙂
Cheers
Vesa
Hey,
you’re right. But it looks cooler 🙂