Querydsl
Querydsl is a framework which enables the construction of type-safe SQL-like queries for multiple backends including JPA, MongoDB and SQL in Java.
Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API.
The goal here is to give you the practical tools to add Querydsl into your project, understand the structure and purpose of the generated classes, and get a basic understanding of how to write type-safe database queries for most common scenarios.
Installation
First, create or edit gradle file gradle.files/querydsl.gradle
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ext { queryDslVersion = '4.4.0' } dependencies { implementation("com.querydsl:querydsl-core:${queryDslVersion}" ) implementation("com.querydsl:querydsl-jpa:${queryDslVersion}" ) annotationProcessor("com.querydsl:querydsl-apt:${queryDslVersion}:jpa" ) annotationProcessor("javax.annotation:javax.annotation-api:1.3.2" ) }
Then, apply that in gradle file bundle.gradle
.
1 2 3 apply from: 'gradle.files/querydsl.gradle'
Or with maven.
Add the following dependencies to your Maven project:
1 2 3 4 5 6 7 8 9 10 11 12 <dependency > <groupId > com.querydsl</groupId > <artifactId > querydsl-apt</artifactId > <version > ${querydsl.version}</version > <scope > provided</scope > </dependency > <dependency > <groupId > com.querydsl</groupId > <artifactId > querydsl-jpa</artifactId > <version > ${querydsl.version}</version > </dependency >
And now, configure the Maven APT plugin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <project > <build > <plugins > ... <plugin > <groupId > com.mysema.maven</groupId > <artifactId > apt-maven-plugin</artifactId > <version > 1.1.3</version > <executions > <execution > <goals > <goal > process</goal > </goals > <configuration > <outputDirectory > target/generated-sources/java</outputDirectory > <processor > com.querydsl.apt.jpa.JPAAnnotationProcessor</processor > </configuration > </execution > </executions > </plugin > ... </plugins > </build > </project >
The JPAAnnotationProcessor
finds domain(or entity, model) types annotated with the javax.persistence.Entity
annotation and generates query types(Prefix with Q letter) for them.
(Deprecated) If you use Hibernate annotations with org.hibernate.annotations.Entity
in your domain types you should use the APT processor com.querydsl.apt.hibernate.HibernateAnnotationProcessor
instead.
Run clean install and you will get your Query types generated into target/generated-sources/java
.
Now you are able to construct JPA query instances and instances of the query domain model.
Configuration
Configuration data source.
1 2 3 4 5 6 7 8 9 10 spring.datasource.url =jdbc:postgresql://postgres:5432 /cloudolife_developmentspring.datasource.username =cloudolifespring.datasource.password =cloudolife
Or application.yml
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 spring: datasource: url: jdbc:postgresql://postgres:5432/cloudolife_development username: cloudolife password: password spring: jpa: show-sql: true properties: hibernate: format_sql: true
Usages
Entity(or Model)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.cloudolife.examples.models;import lombok.*;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;import java.util.UUID;@Data @Entity @Table(name = "users") public class User { @Id @GeneratedValue private Long id; private String code; private String name; }
Querydsl will generate a query type with the simple name QUser
into the same package as User
. QUser
can be used as a statically typed variable in Querydsl queries as a representative for the User type.
QUser
has a default instance variable which can be accessed as a static field:
1 QUser user = QUser.user;
Alternatively you can define your own User variables like this:
1 QUser user = new QUser ("myUser" );
Main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.cloudolife.examples;import com.querydsl.jpa.impl.JPAQueryFactory;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import javax.persistence.EntityManager;@SpringBootApplication public class ColAgreementServiceApplication { public static void main (String[] args) { SpringApplication.run(ColAgreementServiceApplication.class, args); } @Bean public JPAQueryFactory jpaQueryFactory (EntityManager entityManager) { return new JPAQueryFactory (entityManager); } }
Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.cloudolife.examples.services;import com.cloudolife.examples.models.User;import com.cloudolife.examples.models.QUser;import com.querydsl.jpa.impl.JPAQueryFactory;import lombok.extern.java.Log;import java.util.List;@Service @Log public class AgreementService { private final JPAQueryFactory jpaQueryFactory; public AgreementService (JPAQueryFactory jpaQueryFactory) { this .jpaQueryFactory = jpaQueryFactory; } public Agreement queryOne () { log.info("By QueryDSL" ); QAgreement qagreement = QAgreement.agreement; Agreement agreement = jpaQueryFactory.selectFrom(QAgreement.agreement). where(QAgreement.agreement.code.eq("Code" )). fetchFirst(); return agreement; } }
UnitTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.cloudolife.examples;import com.cloudolife.examples.services.UserService;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest class ColAgreementServiceApplicationTests { @Test void contextLoads () { } @Autowired private UserService userService; @Test void testUserServiceQueryOne () { userService.queryOne(); } }
FAQs
Check your gradle file to avodie that error.
1 2 3 4 5 6 7 8 dependencies { implementation("com.querydsl:querydsl-core:${queryDslVersion}" ) implementation("com.querydsl:querydsl-jpa:${queryDslVersion}" ) annotationProcessor("com.querydsl:querydsl-apt:${queryDslVersion}:jpa" ) annotationProcessor("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final" ) annotationProcessor("javax.annotation:javax.annotation-api:1.3.2" ) }
Add Bean
annotation and public JPAQueryFactory jpaQueryFactory(EntityManager entityManager)
method to main class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.cloudolife.examples;import com.querydsl.jpa.impl.JPAQueryFactory;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import javax.persistence.EntityManager;@SpringBootApplication public class ColAgreementServiceApplication { public static void main (String[] args) { SpringApplication.run(ColAgreementServiceApplication.class, args); } @Bean public JPAQueryFactory jpaQueryFactory (EntityManager entityManager) { return new JPAQueryFactory (entityManager); } }
References
[1] Intro to Querydsl | Baeldung - https://www.baeldung.com/intro-to-querydsl
[2] A Guide to Querydsl with JPA | Baeldung - https://www.baeldung.com/querydsl-with-jpa-tutorial
[3] Using Querydsl With Spring Data JPA | by Somnath Musib | Medium - https://musibs.medium.com/using-querydsl-with-spring-data-jpa-a28bfda35ded
[4] Spring Data JPA + QueryDSL: Taking the Best From Both Worlds - DZone Java - https://dzone.com/articles/spring-data-jpa-querydsl-taking-best-from-both-wor
[5] A Quick introduction to Querydsl compared to JPA 2 Criteria Api - Blog j-labs - https://blog.j-labs.pl/quick-introduction-to-querydsl
[5] Custom Search Predicates with SpringBot and QueryDSL | Codebots - https://codebots.com/docs/custom-search-predicates-with-springbot-and-querydsl
[6] Querydsl Extension | Spring Data JDBC - Reference Documentation - https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/#core.extensions.querydsl
[7] querydsl/querydsl: Unified Queries for Java - https://github.com/querydsl/querydsl
[8] Querydsl - Unified Queries for Java - https://querydsl.com/