|
1 |
| -include::{commons}@data-commons::page$repositories/core-extensions.adoc[] |
| 1 | +[[core.extensions]] |
| 2 | += Spring Data Extensions |
| 3 | + |
| 4 | +This section documents a set of Spring Data extensions that enable Spring Data usage in a variety of contexts. |
| 5 | +Currently, most of the integration is targeted towards Spring MVC. |
| 6 | + |
| 7 | +include::{commons}@data-commons::page$repositories/core-extensions-querydsl.adoc[leveloffset=1] |
| 8 | + |
| 9 | +[[ldap.repositories.queries.type-safe]] |
| 10 | +=== Type-safe Query Methods with Querydsl |
| 11 | + |
| 12 | +LDAP repository counterpart integrates with the http://www.querydsl.com/[Querydsl] project, which provides a way to perform type-safe queries. |
| 13 | + |
| 14 | +[quote,Querydsl Team] |
| 15 | +Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API. |
| 16 | + |
| 17 | +It provides the following features: |
| 18 | + |
| 19 | +* Code completion in the IDE (all properties, methods, and operations can be expanded in your favorite Java IDE). |
| 20 | +* Almost no syntactically invalid queries allowed (type-safe on all levels). |
| 21 | +* Domain types and properties can be referenced safely -- no strings involved! |
| 22 | +* Adapts better to refactoring changes in domain types. |
| 23 | +* Incremental query definition is easier. |
| 24 | + |
| 25 | +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. |
| 26 | + |
| 27 | +Querydsl lets you write queries such as the following: |
| 28 | + |
| 29 | +==== |
| 30 | +[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
| 31 | +---- |
| 32 | +QPerson person = QPerson.person; |
| 33 | +List<Person> result = repository.findAll(person.address.zipCode.eq("C0123")); |
| 34 | +
|
| 35 | +Page<Person> page = repository.findAll(person.lastname.contains("a"), |
| 36 | + PageRequest.of(0, 2, Direction.ASC, "lastname")); |
| 37 | +---- |
| 38 | +==== |
| 39 | + |
| 40 | +`QPerson` is a class that is generated by the Java annotation processor. |
| 41 | +See xref:#ldap.repositories.queries.type-safe.apt[Setting up Annotation Processing] for how to set up Annotation Processing with your Build System. |
| 42 | +It is a `Predicate` that lets you write type-safe queries. |
| 43 | +Notice that there are no strings in the query other than the `C0123` value. |
| 44 | + |
| 45 | +You can use the generated `Predicate` class by using the `QuerydslPredicateExecutor` interface, which the following listing shows: |
| 46 | + |
| 47 | +==== |
| 48 | +[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
| 49 | +---- |
| 50 | +public interface QuerydslPredicateExecutor<T> { |
| 51 | +
|
| 52 | + Optional<T> findOne(Predicate predicate); |
| 53 | +
|
| 54 | + List<T> findAll(Predicate predicate); |
| 55 | +
|
| 56 | + List<T> findAll(Predicate predicate, Sort sort); |
| 57 | +
|
| 58 | + List<T> findAll(Predicate predicate, OrderSpecifier<?>... orders); |
| 59 | +
|
| 60 | + Page<T> findAll(Predicate predicate, Pageable pageable); |
| 61 | +
|
| 62 | + List<T> findAll(OrderSpecifier<?>... orders); |
| 63 | +
|
| 64 | + long count(Predicate predicate); |
| 65 | +
|
| 66 | + boolean exists(Predicate predicate); |
| 67 | +
|
| 68 | + <S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction); |
| 69 | +} |
| 70 | +---- |
| 71 | +==== |
| 72 | + |
| 73 | +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: |
| 74 | + |
| 75 | +==== |
| 76 | +[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
| 77 | +---- |
| 78 | +interface PersonRepository extends LdapRepository<Person>, QuerydslPredicateExecutor<Person> { |
| 79 | +
|
| 80 | + // additional query methods go here |
| 81 | +} |
| 82 | +---- |
| 83 | +==== |
| 84 | + |
| 85 | +[[ldap.repositories.queries.type-safe.apt]] |
| 86 | +=== Setting up Annotation Processing |
| 87 | + |
| 88 | +To use Querydsl with Spring Data LDAP, you need to set up annotation processing in your build system that generates the `Q` classes. |
| 89 | +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. |
| 90 | + |
| 91 | +Spring Data LDAP ships with an annotation processor javadoc:org.springframework.data.ldap.repository.support.LdapAnnotationProcessor[] that isn't registered by default. |
| 92 | +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. |
| 93 | +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. |
| 94 | +Hence, you need to activate annotation processing in your build system. |
| 95 | + |
| 96 | +The following example shows how to set up annotation processing by mentioning dependencies and compiler config changes in Maven and Gradle: |
| 97 | + |
| 98 | +[tabs] |
| 99 | +====== |
| 100 | +Maven:: |
| 101 | ++ |
| 102 | +[source,xml,indent=0,subs="verbatim,quotes",role="primary"] |
| 103 | +---- |
| 104 | +<dependencies> |
| 105 | + <dependency> |
| 106 | + <groupId>org.springframework.data</groupId> |
| 107 | + <artifactId>spring-data-ldap</artifactId> |
| 108 | + </dependency> |
| 109 | +
|
| 110 | + <dependency> |
| 111 | + <groupId>com.querydsl</groupId> |
| 112 | + <artifactId>querydsl-core</artifactId> |
| 113 | + <version>${querydslVersion}</version> |
| 114 | + <classifier>jakarta</classifier> |
| 115 | + </dependency> |
| 116 | +
|
| 117 | + <dependency> |
| 118 | + <groupId>com.querydsl</groupId> |
| 119 | + <artifactId>querydsl-apt</artifactId> |
| 120 | + <version>${querydslVersion}</version> |
| 121 | + <classifier>jakarta</classifier> |
| 122 | + <scope>provided</scope> |
| 123 | + </dependency> |
| 124 | +</dependencies> |
| 125 | +
|
| 126 | +<build> |
| 127 | + <plugins> |
| 128 | + <plugin> |
| 129 | + <groupId>org.apache.maven.plugins</groupId> |
| 130 | + <artifactId>maven-compiler-plugin</artifactId> |
| 131 | + <configuration> |
| 132 | + <annotationProcessors> |
| 133 | + <annotationProcessor> |
| 134 | + org.springframework.data.ldap.repository.support.LdapAnnotationProcessor |
| 135 | + </annotationProcessor> |
| 136 | + </annotationProcessors> |
| 137 | +
|
| 138 | + <!-- Recommended: Some IDE's might require this configuration to include generated sources for IDE usage --> |
| 139 | + <generatedTestSourcesDirectory>target/generated-test-sources</generatedTestSourcesDirectory> |
| 140 | + <generatedSourcesDirectory>target/generated-sources</generatedSourcesDirectory> |
| 141 | + </configuration> |
| 142 | + </plugin> |
| 143 | + </plugins> |
| 144 | +</build> |
| 145 | +---- |
| 146 | +
|
| 147 | +Gradle:: |
| 148 | ++ |
| 149 | +==== |
| 150 | +[source,groovy,indent=0,subs="verbatim,quotes",role="secondary"] |
| 151 | +---- |
| 152 | +dependencies { |
| 153 | + implementation 'com.querydsl:querydsl-core:${querydslVersion}:jakarta' |
| 154 | +
|
| 155 | + annotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta' |
| 156 | + annotationProcessor 'org.springframework.data:spring-data-ldap' |
| 157 | +
|
| 158 | + testAnnotationProcessor 'com.querydsl:querydsl-apt:${querydslVersion}:jakarta' |
| 159 | + testAnnotationProcessor 'org.springframework.data:spring-data-ldap' |
| 160 | +} |
| 161 | +
|
| 162 | +tasks.withType(JavaCompile).configureEach { |
| 163 | + options.compilerArgs += [ |
| 164 | + "-processor", |
| 165 | + "org.springframework.data.ldap.repository.support.LdapAnnotationProcessor"] |
| 166 | +} |
| 167 | +---- |
| 168 | +==== |
| 169 | +====== |
| 170 | + |
| 171 | +Note that the setup above shows the simplest usage omitting any other options or dependencies that your project might require. |
| 172 | + |
| 173 | +include::{commons}@data-commons::page$repositories/core-extensions-web.adoc[leveloffset=1] |
| 174 | + |
| 175 | +include::{commons}@data-commons::page$repositories/core-extensions-populators.adoc[leveloffset=1] |
0 commit comments