Browse Source

Refine Querydsl documentation.

Closes #4894
pull/4906/head
Mark Paluch 10 months ago
parent
commit
8eedec2036
No known key found for this signature in database
GPG Key ID: 55BC6374BAA9D973
  1. 1
      src/main/antora/modules/ROOT/nav.adoc
  2. 2
      src/main/antora/modules/ROOT/pages/mongodb.adoc
  3. 226
      src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc
  4. 237
      src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc

1
src/main/antora/modules/ROOT/nav.adoc

@ -41,6 +41,7 @@ @@ -41,6 +41,7 @@
** xref:repositories/core-concepts.adoc[]
** xref:repositories/definition.adoc[]
** xref:mongodb/repositories/repositories.adoc[]
** xref:repositories/core-extensions.adoc[]
** xref:repositories/create-instances.adoc[]
** xref:repositories/query-methods-details.adoc[]
** xref:mongodb/repositories/query-methods.adoc[]

2
src/main/antora/modules/ROOT/pages/mongodb.adoc

@ -13,7 +13,7 @@ Includes integrated object mapping between documents and POJOs. @@ -13,7 +13,7 @@ Includes integrated object mapping between documents and POJOs.
* xref:mongodb/lifecycle-events.adoc[Persistence and mapping lifecycle events].
* xref:mongodb/template-query-operations.adoc[Java-based Query, Criteria, and Update DSLs].
* Automatic implementation of xref:repositories.adoc[Repository interfaces], including support for custom query methods.
* xref:mongodb/repositories/repositories.adoc#mongodb.repositories.queries.type-safe[QueryDSL integration] to support type-safe queries.
* xref:repositories/core-extensions.adoc#mongodb.repositories.queries.type-safe[QueryDSL integration] to support type-safe queries.
* xref:mongodb/client-session-transactions.adoc[Multi-Document Transactions].
* xref:mongodb/template-query-operations.adoc#mongo.geo-json[GeoSpatial integration].

226
src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc

@ -211,229 +211,3 @@ class PersonRepositoryTests { @@ -211,229 +211,3 @@ class PersonRepositoryTests {
The preceding example creates an application context with Spring's unit test support, which performs annotation-based dependency injection into test cases.
Inside the test method, we use the repository to query the datastore.
We hand the repository a `PageRequest` instance that requests the first page of `Person` objects at a page size of 10.
[[mongodb.repositories.queries.type-safe]]
== Type-safe Query Methods with Querydsl
MongoDB repository and its reactive counterpart integrates with the http://www.querydsl.com/[Querydsl] project, which provides a way to perform type-safe queries.
[quote, Querydsl Team]
Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API.
It provides the following features:
* Code completion in the IDE (all properties, methods, and operations can be expanded in your favorite Java IDE).
* Almost no syntactically invalid queries allowed (type-safe on all levels).
* Domain types and properties can be referenced safely -- no strings involved!
* Adapts better to refactoring changes in domain types.
* Incremental query definition is easier.
See the http://www.querydsl.com/static/querydsl/latest/reference/html/[QueryDSL documentation] for how to bootstrap your environment for APT-based code generation using Maven or Ant.
QueryDSL lets you write queries such as the following:
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
QPerson person = QPerson.person;
List<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));
Page<Person> page = repository.findAll(person.lastname.contains("a"),
PageRequest.of(0, 2, Direction.ASC, "lastname"));
----
Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
QPerson person = QPerson.person;
Flux<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));
----
======
`QPerson` is a class that is generated by the Java annotation processor.
See xref:#mongodb.repositories.queries.type-safe.apt[Setting up Annotation Processing] for how to setup Annotation Processing with your Build System.
It is a `Predicate` that lets you write type-safe queries.
Notice that there are no strings in the query other than the `C0123` value.
You can use the generated `Predicate` class by using the `QuerydslPredicateExecutor` / `ReactiveQuerydslPredicateExecutor` interface, which the following listing shows:
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public interface QuerydslPredicateExecutor<T> {
Optional<T> findOne(Predicate predicate);
List<T> findAll(Predicate predicate);
List<T> findAll(Predicate predicate, Sort sort);
List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Page<T> findAll(Predicate predicate, Pageable pageable);
List<T> findAll(OrderSpecifier<?>... orders);
long count(Predicate predicate);
boolean exists(Predicate predicate);
<S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}
----
Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
interface ReactiveQuerydslPredicateExecutor<T> {
Mono<T> findOne(Predicate predicate);
Flux<T> findAll(Predicate predicate);
Flux<T> findAll(Predicate predicate, Sort sort);
Flux<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Flux<T> findAll(OrderSpecifier<?>... orders);
Mono<Long> count(Predicate predicate);
Mono<Boolean> exists(Predicate predicate);
<S extends T, R, P extends Publisher<R>> P findBy(Predicate predicate,
Function<FluentQuery.ReactiveFluentQuery<S>, P> queryFunction);
}
----
======
To use this in your repository implementation, add it to the list of repository interfaces from which your interface inherits, as the following example shows:
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
interface PersonRepository extends MongoRepository<Person, String>, QuerydslPredicateExecutor<Person> {
// additional query methods go here
}
----
Reactive::
+
====
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
interface PersonRepository extends ReactiveMongoRepository<Person, String>, ReactiveQuerydslPredicateExecutor<Person> {
// additional query methods go here
}
----
NOTE: Please note that joins (DBRef's) are not supported with Reactive MongoDB support.
====
======
[[mongodb.repositories.queries.type-safe.apt]]
=== Setting up Annotation Processing
To use Querydsl with Spring Data MongoDB, you need to set up annotation processing in your build system that generates the `Q` classes.
While you could write the `Q` classes by hand, it is recommended to use the Querydsl annotation processor to generate them for you to keep your `Q` classes in sync with your domain model.
Spring Data MongoDB ships with an annotation processor javadoc:org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor[] that isn't registered by default.
Typically, annotation processors are registered through Java's service loader via `META-INF/services/javax.annotation.processing.Processor` that also activates these once you have them on the class path.
Most Spring Data users do not use Querydsl, so it does not make sense to require additional mandatory dependencies for projects that would not benefit from Querydsl.
Hence, you need to activate annotation processing in your build system.
The following example shows how to set up annotation processing by mentioning dependencies and compiler config changes in Maven and Gradle:
[tabs]
======
Maven::
+
[source,xml,indent=0,subs="verbatim,quotes",role="primary"]
----
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-mongodb</artifactId>
<version>${querydslVersion}</version>
<classifier>jakarta</classifier>
<!-- Recommended: Exclude the mongo-java-driver to avoid version conflicts -->
<exclusions>
<exclusion>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydslVersion}</version>
<classifier>jakarta</classifier>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessors>
<annotationProcessor>
org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
</annotationProcessor>
</annotationProcessors>
<!-- Recommended: Some IDE's might require this configuration to include generated sources for IDE usage -->
<generatedTestSourcesDirectory>target/generated-test-sources</generatedTestSourcesDirectory>
<generatedSourcesDirectory>target/generated-sources</generatedSourcesDirectory>
</configuration>
</plugin>
</plugins>
</build>
----
Gradle::
+
====
[source,groovy,indent=0,subs="verbatim,quotes",role="secondary"]
----
dependencies {
implementation 'com.querydsl:querydsl-mongodb:${querydslVersion}:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta'
annotationProcessor 'org.springframework.data:spring-data-mongodb'
testAnnotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}'
testAnnotationProcessor 'org.springframework.data:spring-data-mongodb'
}
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [
"-processor",
"org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor"]
}
----
====
======
Note that the setup above shows the simplest usage omitting any other options or dependencies that your project might require.

237
src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc

@ -1 +1,236 @@ @@ -1 +1,236 @@
include::{commons}@data-commons::page$repositories/core-extensions.adoc[]
[[core.extensions]]
= Spring Data Extensions
This section documents a set of Spring Data extensions that enable Spring Data usage in a variety of contexts.
Currently, most of the integration is targeted towards Spring MVC.
include::{commons}@data-commons::page$repositories/core-extensions-querydsl.adoc[leveloffset=1]
[[mongodb.repositories.queries.type-safe]]
=== Type-safe Query Methods with Querydsl
MongoDB repository and its reactive counterpart integrates with the http://www.querydsl.com/[Querydsl] project, which provides a way to perform type-safe queries.
[quote,Querydsl Team]
Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API.
It provides the following features:
* Code completion in the IDE (all properties, methods, and operations can be expanded in your favorite Java IDE).
* Almost no syntactically invalid queries allowed (type-safe on all levels).
* Domain types and properties can be referenced safely -- no strings involved!
* Adapts better to refactoring changes in domain types.
* Incremental query definition is easier.
See the http://www.querydsl.com/static/querydsl/latest/reference/html/[QueryDSL documentation] for how to bootstrap your environment for APT-based code generation using Maven or Ant.
QueryDSL lets you write queries such as the following:
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
QPerson person = QPerson.person;
List<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));
Page<Person> page = repository.findAll(person.lastname.contains("a"),
PageRequest.of(0, 2, Direction.ASC, "lastname"));
----
Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
QPerson person = QPerson.person;
Flux<Person> result = repository.findAll(person.address.zipCode.eq("C0123"));
----
======
`QPerson` is a class that is generated by the Java annotation processor.
See xref:#mongodb.repositories.queries.type-safe.apt[Setting up Annotation Processing] for how to setup Annotation Processing with your Build System.
It is a `Predicate` that lets you write type-safe queries.
Notice that there are no strings in the query other than the `C0123` value.
You can use the generated `Predicate` class by using the `QuerydslPredicateExecutor` / `ReactiveQuerydslPredicateExecutor` interface, which the following listing shows:
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
public interface QuerydslPredicateExecutor<T> {
Optional<T> findOne(Predicate predicate);
List<T> findAll(Predicate predicate);
List<T> findAll(Predicate predicate, Sort sort);
List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Page<T> findAll(Predicate predicate, Pageable pageable);
List<T> findAll(OrderSpecifier<?>... orders);
long count(Predicate predicate);
boolean exists(Predicate predicate);
<S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);
}
----
Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
interface ReactiveQuerydslPredicateExecutor<T> {
Mono<T> findOne(Predicate predicate);
Flux<T> findAll(Predicate predicate);
Flux<T> findAll(Predicate predicate, Sort sort);
Flux<T> findAll(Predicate predicate, OrderSpecifier<?>... orders);
Flux<T> findAll(OrderSpecifier<?>... orders);
Mono<Long> count(Predicate predicate);
Mono<Boolean> exists(Predicate predicate);
<S extends T, R, P extends Publisher<R>> P findBy(Predicate predicate,
Function<FluentQuery.ReactiveFluentQuery<S>, P> queryFunction);
}
----
======
To use this in your repository implementation, add it to the list of repository interfaces from which your interface inherits, as the following example shows:
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
interface PersonRepository extends MongoRepository<Person, String>, QuerydslPredicateExecutor<Person> {
// additional query methods go here
}
----
Reactive::
+
====
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
interface PersonRepository extends ReactiveMongoRepository<Person, String>, ReactiveQuerydslPredicateExecutor<Person> {
// additional query methods go here
}
----
NOTE: Please note that joins (DBRef's) are not supported with Reactive MongoDB support.
====
======
[[mongodb.repositories.queries.type-safe.apt]]
=== Setting up Annotation Processing
To use Querydsl with Spring Data MongoDB, you need to set up annotation processing in your build system that generates the `Q` classes.
While you could write the `Q` classes by hand, it is recommended to use the Querydsl annotation processor to generate them for you to keep your `Q` classes in sync with your domain model.
Spring Data MongoDB ships with an annotation processor javadoc:org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor[] that isn't registered by default.
Typically, annotation processors are registered through Java's service loader via `META-INF/services/javax.annotation.processing.Processor` that also activates these once you have them on the class path.
Most Spring Data users do not use Querydsl, so it does not make sense to require additional mandatory dependencies for projects that would not benefit from Querydsl.
Hence, you need to activate annotation processing in your build system.
The following example shows how to set up annotation processing by mentioning dependencies and compiler config changes in Maven and Gradle:
[tabs]
======
Maven::
+
[source,xml,indent=0,subs="verbatim,quotes",role="primary"]
----
<dependencies>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-mongodb</artifactId>
<version>${querydslVersion}</version>
<classifier>jakarta</classifier>
<!-- Recommended: Exclude the mongo-java-driver to avoid version conflicts -->
<exclusions>
<exclusion>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydslVersion}</version>
<classifier>jakarta</classifier>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessors>
<annotationProcessor>
org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
</annotationProcessor>
</annotationProcessors>
<!-- Recommended: Some IDE's might require this configuration to include generated sources for IDE usage -->
<generatedTestSourcesDirectory>target/generated-test-sources</generatedTestSourcesDirectory>
<generatedSourcesDirectory>target/generated-sources</generatedSourcesDirectory>
</configuration>
</plugin>
</plugins>
</build>
----
Gradle::
+
====
[source,groovy,indent=0,subs="verbatim,quotes",role="secondary"]
----
dependencies {
implementation 'com.querydsl:querydsl-mongodb:${querydslVersion}:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta'
annotationProcessor 'org.springframework.data:spring-data-mongodb'
testAnnotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta'
testAnnotationProcessor 'org.springframework.data:spring-data-mongodb'
}
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [
"-processor",
"org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor"]
}
----
====
======
Note that the setup above shows the simplest usage omitting any other options or dependencies that your project might require.
include::{commons}@data-commons::page$repositories/core-extensions-web.adoc[leveloffset=1]
include::{commons}@data-commons::page$repositories/core-extensions-populators.adoc[leveloffset=1]

Loading…
Cancel
Save