Partner – JPA Buddy – NPI (tag=JPA/Hibernate)
announcement - icon

The right tools can and will save a lot of time. As long as you are using Hibernate and IntelliJ IDEA you can boost your coding speed and quality with JPA Buddy. It will help in a lot of the day-to-day work:

  • Creating JPA entities that follow best practices for efficient mapping
  • Creating DTOs from entities and MapStruct mappers using convenient visual tools
  • Generating entities from the existing database or Swagger-generated POJOs
  • Visually composing methods for Spring Data JPA repositories
  • Generating differential SQL to update your schema in accordance with your changes in entities
  • Autogenerating Flyway migrations and Liquibase changelogs comparing entities with the database or two databases
  • … and a lot more

Simply put, you'll learn and use the best practices of Hibernate and surrounding technology and become a lot more!

Definitely visit the JPA Buddy site to see its features in action closer.

Persistence top

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:


1. Overview

Querydsl is an extensive Java framework, which helps with creating and running type-safe queries in a domain specific language that is similar to SQL.

In this article we'll explore Querydsl with the Java Persistence API.

A quick side note here is that HQL for Hibernate was the first target language for Querydsl, but nowadays it supports JPA, JDO, JDBC, Lucene, Hibernate Search, MongoDB, Collections and RDFBean as backends.

2. Preparations

Let's first add the necessary dependencies into our Maven project:





And now let's configure the Maven APT plugin:


The JPAAnnotationProcessor will find domain types annotated with javax.persistence.Entity annotation and generates query types for them.

3. Queries With Querydsl

Queries are constructed based on generated query types that reflect the properties of your domain types. Also function/method invocations are constructed in a fully type-safe manner.

The query paths and operations are the same in all implementations and also the Query interfaces have a common base interface.

3.1. An Entity and the Querydsl Query Type

Let's first define a simple entity we're going to make use of as we go through examples:

public class Person {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstname;

    private String surname;
    Person() {

    public Person(String firstname, String surname) {
        this.firstname = firstname;
        this.surname = surname;

    // standard getters and setters


Querydsl will generate a query type with the simple name QPerson into the same package as Person. QPerson can be used as a statically typed variable in Querydsl queries as a representative for the Person type.

First – QPerson has a default instance variable which can be accessed as a static field:

QPerson person = QPerson.person;

Alternatively you can define your own Person variables like this:

QPerson person = new QPerson("Erich", "Gamma");

3.2. Build Query Using JPAQuery

We can now use JPAQuery instances for our queries:

JPAQuery query = new JPAQuery(entityManager);

Note that the entityManager is a JPA EntityManager.

Let's now retrieve all the persons with the first name “Kent” as a quick example:

QPerson person = QPerson.person;
List<Person> persons = query.from(person).where(person.firstName.eq("Kent")).list(person);

The from call defines the query source and projection, the where part defines the filter and list tells Querydsl to return all matched elements.

We can also use multiple filters:

query.from(person).where(person.firstName.eq("Kent"), person.surname.eq("Beck"));



In native JPQL form the query would be written like this:

select person from Person as person where person.firstName = "Kent" and person.surname = "Beck"

If you want to combine the filters via “or” then use the following pattern:


4. Ordering and Aggregation in Querydsl

Let's now have a look at how ordering and aggregation work within the Querydsl library.

4.1. Ordering

We'll start by ordering our results in descending order by the surname field:

QPerson person = QPerson.person;
List<Person> persons = query.from(person)

4.2. Aggregation

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 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<String, Integer> results = 

5. Testing With Querydsl

Now, let's define a DAO implementation using Querydsl – and let's define the following search operation:

public List<Person> findPersonsByFirstnameQuerydsl(String firstname) {
    JPAQuery query = new JPAQuery(em);
    QPerson person = QPerson.person;
    return query.from(person).where(person.firstname.eq(firstname)).list(person);

And now let's build a few tests using this new DAO and let's use Querydsl to search for newly created Person objects (implemented in PersonDao class) and in another test aggregation using GroupBy class is tested:

private PersonDao personDao;

public void givenExistingPersons_whenFindingPersonByFirstName_thenFound() { Person("Erich", "Gamma"));
    Person person = new Person("Kent", "Beck");; Person("Ralph", "Johnson"));

    Person personFromDb =  personDao.findPersonsByFirstnameQuerydsl("Kent").get(0);
    Assert.assertEquals(person.getId(), personFromDb.getId());

public void givenExistingPersons_whenFindingMaxAgeByName_thenFound() { Person("Kent", "Gamma", 20)); Person("Ralph", "Johnson", 35)); Person("Kent", "Zivago", 30));

    Map<String, Integer> maxAge = personDao.findMaxAgeByName();
    Assert.assertTrue(maxAge.size() == 2);
    Assert.assertSame(35, maxAge.get("Ralph"));
    Assert.assertSame(30, maxAge.get("Kent"));

6. Conclusion

This tutorial illustrated how to build JPA project using Querydsl.

The full implementation of this article can be found in the github project – this is an Eclipse based maven project, so it should be easy to import and run as it is.

A quick note here is – run a simple maven build (mvn clean install) to generate the types into target/generated-sources – and then, if you're using Eclipse – include the folder as a source folder of the project.

Persistence bottom

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:

Persistence footer banner
Comments are closed on this article!