diff --git a/src/main/antora/modules/ROOT/nav.adoc b/src/main/antora/modules/ROOT/nav.adoc index 7414dfcfb..221f47c01 100644 --- a/src/main/antora/modules/ROOT/nav.adoc +++ b/src/main/antora/modules/ROOT/nav.adoc @@ -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[] diff --git a/src/main/antora/modules/ROOT/pages/mongodb.adoc b/src/main/antora/modules/ROOT/pages/mongodb.adoc index de07ceb92..907cbf06b 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb.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]. diff --git a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc b/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc index 79c5566d1..0746a0909 100644 --- a/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc +++ b/src/main/antora/modules/ROOT/pages/mongodb/repositories/repositories.adoc @@ -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 result = repository.findAll(person.address.zipCode.eq("C0123")); - -Page 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 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 { - - Optional findOne(Predicate predicate); - - List findAll(Predicate predicate); - - List findAll(Predicate predicate, Sort sort); - - List findAll(Predicate predicate, OrderSpecifier... orders); - - Page findAll(Predicate predicate, Pageable pageable); - - List findAll(OrderSpecifier... orders); - - long count(Predicate predicate); - - boolean exists(Predicate predicate); - - R findBy(Predicate predicate, Function, R> queryFunction); -} ----- - -Reactive:: -+ -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- -interface ReactiveQuerydslPredicateExecutor { - - Mono findOne(Predicate predicate); - - Flux findAll(Predicate predicate); - - Flux findAll(Predicate predicate, Sort sort); - - Flux findAll(Predicate predicate, OrderSpecifier... orders); - - Flux findAll(OrderSpecifier... orders); - - Mono count(Predicate predicate); - - Mono exists(Predicate predicate); - - > P findBy(Predicate predicate, - Function, 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, QuerydslPredicateExecutor { - - // additional query methods go here -} ----- - -Reactive:: -+ -==== -[source,java,indent=0,subs="verbatim,quotes",role="secondary"] ----- - -interface PersonRepository extends ReactiveMongoRepository, ReactiveQuerydslPredicateExecutor { - - // 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"] ----- - - - com.querydsl - querydsl-mongodb - ${querydslVersion} - jakarta - - - - - org.mongodb - mongo-java-driver - - - - - - com.querydsl - querydsl-apt - ${querydslVersion} - jakarta - provided - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor - - - - - target/generated-test-sources - target/generated-sources - - - - ----- - -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. diff --git a/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc b/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc index a7c2ff8d3..6a3cc11e5 100644 --- a/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc +++ b/src/main/antora/modules/ROOT/pages/repositories/core-extensions.adoc @@ -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 result = repository.findAll(person.address.zipCode.eq("C0123")); + +Page 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 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 { + + Optional findOne(Predicate predicate); + + List findAll(Predicate predicate); + + List findAll(Predicate predicate, Sort sort); + + List findAll(Predicate predicate, OrderSpecifier... orders); + + Page findAll(Predicate predicate, Pageable pageable); + + List findAll(OrderSpecifier... orders); + + long count(Predicate predicate); + + boolean exists(Predicate predicate); + + R findBy(Predicate predicate, Function, R> queryFunction); +} +---- + +Reactive:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- +interface ReactiveQuerydslPredicateExecutor { + + Mono findOne(Predicate predicate); + + Flux findAll(Predicate predicate); + + Flux findAll(Predicate predicate, Sort sort); + + Flux findAll(Predicate predicate, OrderSpecifier... orders); + + Flux findAll(OrderSpecifier... orders); + + Mono count(Predicate predicate); + + Mono exists(Predicate predicate); + + > P findBy(Predicate predicate, + Function, 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, QuerydslPredicateExecutor { + + // additional query methods go here +} +---- + +Reactive:: ++ +==== +[source,java,indent=0,subs="verbatim,quotes",role="secondary"] +---- + +interface PersonRepository extends ReactiveMongoRepository, ReactiveQuerydslPredicateExecutor { + + // 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"] +---- + + + com.querydsl + querydsl-mongodb + ${querydslVersion} + jakarta + + + + + org.mongodb + mongo-java-driver + + + + + + com.querydsl + querydsl-apt + ${querydslVersion} + jakarta + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor + + + + + target/generated-test-sources + target/generated-sources + + + + +---- + +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]