From 90038b35ffa4b68158e74aa2b34ef904d160e3ac Mon Sep 17 00:00:00 2001 From: Vicaria Barker Date: Mon, 17 Jan 2022 14:14:02 +0100 Subject: [PATCH 1/2] Added querydsl tutorial --- querydsl/files/FruitFragment.java | 17 ++++ querydsl/files/FruitFragmentImpl.java | 67 +++++++++++++ querydsl/files/findAllQueryDslFunc.asciidoc | 34 +++++++ querydsl/files/function.txt | 1 + .../files/querydsl-annotation-processor.txt | 16 ++++ querydsl/files/querydsl-dependencies.txt | 11 +++ querydsl/index.asciidoc | 93 +++++++++++++++++++ 7 files changed, 239 insertions(+) create mode 100644 querydsl/files/FruitFragment.java create mode 100644 querydsl/files/FruitFragmentImpl.java create mode 100644 querydsl/files/findAllQueryDslFunc.asciidoc create mode 100644 querydsl/files/function.txt create mode 100644 querydsl/files/querydsl-annotation-processor.txt create mode 100644 querydsl/files/querydsl-dependencies.txt create mode 100644 querydsl/index.asciidoc diff --git a/querydsl/files/FruitFragment.java b/querydsl/files/FruitFragment.java new file mode 100644 index 00000000..cac3e242 --- /dev/null +++ b/querydsl/files/FruitFragment.java @@ -0,0 +1,17 @@ +package org.acme.spring.data.jpa.repo.fruit; + +import java.util.List; + +import org.acme.spring.data.jpa.model.Fruit; + +public interface FruitFragment { + + public List findAllQueryDslName(String name); + + public List findAllQueryDslMaxPriceDesc(Float price); + + public List findAllQueryDslMinPriceAsc(Float price); + + public List findAllQueryDslPriceRange(Float min, Float max); + +} diff --git a/querydsl/files/FruitFragmentImpl.java b/querydsl/files/FruitFragmentImpl.java new file mode 100644 index 00000000..aa6d312a --- /dev/null +++ b/querydsl/files/FruitFragmentImpl.java @@ -0,0 +1,67 @@ +package org.acme.spring.data.jpa.repo.fruit; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.persistence.EntityManager; + +import org.acme.spring.data.jpa.model.Fruit; +import org.acme.spring.data.jpa.model.QFruit; + +import com.querydsl.jpa.impl.JPAQuery; + +public class FruitFragmentImpl implements FruitFragment { + + @Inject + EntityManager em; + + @Override + public List findAllQueryDslName(String name) { + + QFruit fruit = QFruit.fruit; + JPAQuery query = new JPAQuery(this.em); + query.from(fruit); + if (name != null && !name.isEmpty()) { + query.where(fruit.name.eq(name)); + } + return query.orderBy(fruit.name.desc()).fetch(); + } + + @Override + public List findAllQueryDslMaxPriceDesc(Float price) { + + QFruit fruit = QFruit.fruit; + JPAQuery query = new JPAQuery(this.em); + query.from(fruit); + if (price != null && price != 0) { + query.where(fruit.price.loe(price)); + } + return query.orderBy(fruit.price.desc()).fetch(); + } + + @Override + public List findAllQueryDslMinPriceAsc(Float price) { + + QFruit fruit = QFruit.fruit; + JPAQuery query = new JPAQuery(this.em); + query.from(fruit); + if (price != null && price != 0) { + query.where(fruit.price.goe(price)); + } + return query.orderBy(fruit.price.asc()).fetch(); + } + + @Override + public List findAllQueryDslPriceRange(Float min, Float max) { + + QFruit fruit = QFruit.fruit; + JPAQuery query = new JPAQuery(this.em); + query.from(fruit); + if (min != null && min != 0 && max != null && max != 0) { + query.where(fruit.price.between(min, max)); + } + return query.orderBy(fruit.price.desc()).fetch(); + } + +} diff --git a/querydsl/files/findAllQueryDslFunc.asciidoc b/querydsl/files/findAllQueryDslFunc.asciidoc new file mode 100644 index 00000000..22657e9d --- /dev/null +++ b/querydsl/files/findAllQueryDslFunc.asciidoc @@ -0,0 +1,34 @@ +Now we can implement Querydsl-queries in the `FruitFragmentImpl`. The class requires a JPA `EntityManager` to interact with the persistent entities, which is passed to the `JPAQuery` constructor when instantiating a query. + +In order to define the `Fruit`-entity as the source of the query, we need to create its Q-type first by accessing its static `fruit` field. Then, we can call `query.from(fruit)`. + +To retrieve a fruit with a given name, we can use a `where`-clause with the `eq` (equals) operator to get fruits with the name equal to the one passed to the function parameter. Additionally, we can sort the results by name in descending alphabetical order by calling `query.orderBy(fruit.name.desc())` before fetching the result. + +public class FruitFragmentImpl implements FruitFragment { + + @Inject + EntityManager em; + + @Override + public List findAllQueryDslName(String name) { + + JPAQuery query = new JPAQuery(this.em); + QFruit fruit = QFruit.fruit; + query.from(fruit); + if (name != null && !name.isEmpty()) { + query.where(fruit.name.eq(name)); + } + return query.orderBy(fruit.name.desc()).fetch(); + } + +We can also get fruits in a given price range by calling `fruit.price.between(min, max)` in the `where`-clause. To see usage of further comparators, see the `findAllQueryDslMaxPriceDesc`and `findAllQueryDslMinPriceAsc` functions. + + @Override + public List findAllQueryDslPriceRange(Float min, Float max) { + ... + if (min != null && min != 0 && max != null && max != 0) { + query.where(fruit.price.between(min, max)); + } + return query.orderBy(fruit.price.desc()).fetch(); + } + diff --git a/querydsl/files/function.txt b/querydsl/files/function.txt new file mode 100644 index 00000000..3875dade --- /dev/null +++ b/querydsl/files/function.txt @@ -0,0 +1 @@ +return this.fruitRepository.findAllQueryDslName(name); \ No newline at end of file diff --git a/querydsl/files/querydsl-annotation-processor.txt b/querydsl/files/querydsl-annotation-processor.txt new file mode 100644 index 00000000..76f28cb3 --- /dev/null +++ b/querydsl/files/querydsl-annotation-processor.txt @@ -0,0 +1,16 @@ + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + + process + + + target/generated-sources/java + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + \ No newline at end of file diff --git a/querydsl/files/querydsl-dependencies.txt b/querydsl/files/querydsl-dependencies.txt new file mode 100644 index 00000000..801ce87b --- /dev/null +++ b/querydsl/files/querydsl-dependencies.txt @@ -0,0 +1,11 @@ + + com.querydsl + querydsl-apt + 4.1.3 + provided + + + com.querydsl + querydsl-jpa + 4.1.3 + diff --git a/querydsl/index.asciidoc b/querydsl/index.asciidoc new file mode 100644 index 00000000..b59135d7 --- /dev/null +++ b/querydsl/index.asciidoc @@ -0,0 +1,93 @@ += Querydsl Tutorial +==== +This tutorial will teach you how to integrate link:https://querydsl.com/[Querydsl] into a Spring or Quarkus project and how to build Querydsl queries. +## Prerequisites +* Installed devonfw IDE +* User should have basic Java development experience + +## Learning goals. +Here in this tutorial you will learn +* To integrate Querydsl in your project +* To build Querydsl expressions +==== + +[step] +-- +restoreDevonfwIde(["java","mvn"]) +-- + +==== +devonfw IDE has been installed for you. + +First, clone the `QueryDslTutorial` repository from GitHub. It contains an application with a simple REST service. +[step] +== Clone QueryDslTutorial repository +-- +cloneRepository("", "https://github.com/EduardKrieger/QueryDslTutorial.git") +-- + +In the next step, integrate Querydsl into your Maven project. +==== + +[step] +== Add Querydsl dependencies to Maven Project +-- +changeFile("QueryDslTutorial/pom.xml" , {"file": "files/querydsl-dependencies.txt", "placeholder": ""}) +changeFile("QueryDslTutorial/pom.xml" , {"file": "files/querydsl-annotation-processor.txt", "placeholder": ""}) +-- + +Next, navigate to the devonfw/QueryDslTutorial directory. +[step] +-- +changeWorkspace("devonfw/workspaces/main/QueryDslTutorial") +-- + +The data model consists of a Fruit entity with Id, name, color, and price fields. + +To extend the application with custom queries in Querydsl, we need to create a FruitFragment-interface and its implementation. This will be extended by the FruitRepository along with the CrudRepository. + +[step] +== Create FruitFragment Interface +-- +createFile("src/main/java/org/acme/spring/data/jpa/repo/fruit/FruitFragment.java","files/FruitFragment.java") +-- + +[step] +== Extend FruitRepository with FruitFragment Interface +-- +changeFile("src/main/java/org/acme/spring/data/jpa/repo/fruit/FruitRepository.java", {"content": "public interface FruitRepository extends CrudRepository, FruitFragment {", "placeholder": "public interface FruitRepository extends CrudRepository {"}) +-- + +[step] +== Implement FruitFragment Interface +-- +createFile("src/main/java/org/acme/spring/data/jpa/repo/fruit/FruitFragmentImpl.java","files/FruitFragmentImpl.java") +-- + +[step] +== Querying with Querydsl +-- +displayContent("Querydsl Expressions", [{ "file": "files/findAllQueryDslFunc.asciidoc" }]) +-- + +[step] +== Implement GET-Request in FruitResource +-- +changeFile("src/main/java/org/acme/spring/data/jpa/repo/fruit/FruitResource.java", {"placeholder": "return null;", "file": "files/function.txt"}) +-- +==== +Now you can run the application in development mode. +[step] +== Run Application +-- +executeCommand("mvn compile quarkus:dev", "mvn compile quarkus:dev") +-- + +Accessing the application with the following link will send a GET-request for fruits named Cherry. The `FruitResource` will call the `FindByName` method and pass the `name` parameter to the `FruitRepository`'s `findAllQueryDslName` method, which it inherents from the `FruitFragment` interface. The querying occurs in the method's implementation, as explained in step 6. +https://[[HOST_SUBDOMAIN]]-8080-[[KATACODA_HOST]].environments.katacoda.com/fruits/name/Cherry +==== + +==== +== Conclusion +To summarize, we learned how to integrate Querydsl into your Maven project and querying with Querydsl. For more information on queries, visit the Querydsl link:https://querydsl.com/static/querydsl/latest/reference/html_single/[documentation] +==== \ No newline at end of file From e725eecf7be93f7a6fb219f06f0b21749087c8b8 Mon Sep 17 00:00:00 2001 From: Rafael Luis Vicaria Barker <94548175+rafaelvicariabarker@users.noreply.github.com> Date: Thu, 24 Feb 2022 10:02:12 +0100 Subject: [PATCH 2/2] made changes based on Julian's review --- querydsl/index.asciidoc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/querydsl/index.asciidoc b/querydsl/index.asciidoc index b59135d7..aef8cbb3 100644 --- a/querydsl/index.asciidoc +++ b/querydsl/index.asciidoc @@ -17,7 +17,7 @@ restoreDevonfwIde(["java","mvn"]) -- ==== -devonfw IDE has been installed for you. +devonfw-ide has been installed for you. First, clone the `QueryDslTutorial` repository from GitHub. It contains an application with a simple REST service. [step] @@ -26,7 +26,8 @@ First, clone the `QueryDslTutorial` repository from GitHub. It contains an appli cloneRepository("", "https://github.com/EduardKrieger/QueryDslTutorial.git") -- -In the next step, integrate Querydsl into your Maven project. +In order to use Querydsl, we need to add the Querydsl dependencies to our Maven project and configure the Maven APT plugin. +The JPAAnnotationProcessor will find domain types annotated with the javax.persistence.Entity annotation and generate query types for them. ==== [step] @@ -80,7 +81,7 @@ Now you can run the application in development mode. [step] == Run Application -- -executeCommand("mvn compile quarkus:dev", "mvn compile quarkus:dev") +executeCommand("devon mvn compile quarkus:dev", "devon mvn compile quarkus:dev", "quarkus.http.host=0.0.0.0") -- Accessing the application with the following link will send a GET-request for fruits named Cherry. The `FruitResource` will call the `FindByName` method and pass the `name` parameter to the `FruitRepository`'s `findAllQueryDslName` method, which it inherents from the `FruitFragment` interface. The querying occurs in the method's implementation, as explained in step 6.