@@ -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[]
|
||||
|
||||
@@ -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].
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user