diff --git a/README.md b/README.md
index 8090c670..bfee187f 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ We have separate folders for the samples of individual modules:
* `java8` - Example of how to use Spring Data MongoDB with Java 8 date time types as well as the usage of `Optional` as return type for repository methods. Note, this project requires to be build with JDK 8.
* `kotlin` - Example for using Cassandra with MongoDB.
* `query-by-example` - Example project showing usage of Query by Example with MongoDB.
+* `querydsl` - Example project showing sync/reactive [Querydsl](https://github.com/querydsl/querydsl) support for MongoDB.
* `reactive` - Example project to show reactive template and repository support.
* `security` - Example project showing usage of Spring Security with MongoDB.
* `text-search` - Example project showing usage of MongoDB text search feature.
diff --git a/mongodb/pom.xml b/mongodb/pom.xml
index 277a1c6a..5f6246fe 100644
--- a/mongodb/pom.xml
+++ b/mongodb/pom.xml
@@ -31,6 +31,7 @@
text-search
transactions
schema-validation
+ querydsl
util
diff --git a/mongodb/querydsl/README.md b/mongodb/querydsl/README.md
new file mode 100644
index 00000000..6d2082bf
--- /dev/null
+++ b/mongodb/querydsl/README.md
@@ -0,0 +1,34 @@
+# Spring Data MongoDB - Querydsl example
+
+This project contains samples of [Querydsl](https://github.com/querydsl/querydsl) usage in Spring Data MongoDB.
+
+Querydsl is a framework which enables the construction of fluent, type-safe queries for multiple backends including MongoDB.
+Spring Data integrates with Querydsl via `QuerydslPredicateExecutor` and its reactive counterpart `ReactiveQuerydslPredicateExecutor`.
+
+**NOTE**: You may have to run `mvn compile` to generate the required `Q` classes first.
+
+## Sync
+
+```java
+interface SyncCustomerRepository
+ extends CrudRepository, QuerydslPredicateExecutor { }
+
+@Autowired SyncCustomerRepository repository;
+
+// ...
+
+List result = repository.findAll(QCustomer.customer.lastname.eq("Matthews"));
+```
+
+## Reactive
+
+```java
+interface ReactiveCustomerRepository
+ extends ReactiveCrudRepository, ReactiveQuerydslPredicateExecutor { }
+
+@Autowired ReactiveCustomerRepository repository;
+
+// ...
+
+Flux result = repository.findAll(QCustomer.customer.lastname.eq("Matthews"));
+```
diff --git a/mongodb/querydsl/pom.xml b/mongodb/querydsl/pom.xml
new file mode 100644
index 00000000..24ee33e7
--- /dev/null
+++ b/mongodb/querydsl/pom.xml
@@ -0,0 +1,59 @@
+
+ 4.0.0
+
+ spring-data-mongodb-querydsl-example
+
+ Spring Data MongoDB - Querydsl Example
+
+
+ org.springframework.data.examples
+ spring-data-mongodb-examples
+ 2.0.0.BUILD-SNAPSHOT
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb-reactive
+
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+
+
+
+
+ com.mysema.maven
+ apt-maven-plugin
+ ${apt.version}
+
+
+ com.querydsl
+ querydsl-apt
+ ${querydsl.version}
+
+
+
+
+ generate-sources
+
+ process
+
+
+ target/generated-sources/queries
+ org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor
+ true
+
+
+
+
+
+
+
+
+
diff --git a/mongodb/querydsl/src/main/java/example/springdata/mongodb/Customer.java b/mongodb/querydsl/src/main/java/example/springdata/mongodb/Customer.java
new file mode 100644
index 00000000..97dccbac
--- /dev/null
+++ b/mongodb/querydsl/src/main/java/example/springdata/mongodb/Customer.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb;
+
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.util.Assert;
+
+/**
+ * An entity to represent a customer.
+ *
+ * @author Christoph Strobl
+ */
+@Document
+public class Customer {
+
+ private String id, firstname, lastname;
+
+ /**
+ * Creates a new {@link Customer} with the given firstname and lastname.
+ *
+ * @param firstname must not be {@literal null} or empty.
+ * @param lastname must not be {@literal null} or empty.
+ */
+ public Customer(String firstname, String lastname) {
+
+ Assert.hasText(firstname, "Firstname must not be null or empty!");
+ Assert.hasText(lastname, "Lastname must not be null or empty!");
+
+ this.firstname = firstname;
+ this.lastname = lastname;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+
+ @Override
+ public String toString() {
+ return "Customer{" + "id='" + id + '\'' + ", firstname='" + firstname + '\'' + ", lastname='" + lastname + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ Customer customer = (Customer) o;
+
+ if (id != null ? !id.equals(customer.id) : customer.id != null)
+ return false;
+ if (firstname != null ? !firstname.equals(customer.firstname) : customer.firstname != null)
+ return false;
+ return lastname != null ? lastname.equals(customer.lastname) : customer.lastname == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = id != null ? id.hashCode() : 0;
+ result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
+ result = 31 * result + (lastname != null ? lastname.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/mongodb/querydsl/src/main/java/example/springdata/mongodb/reactive/ApplicationConfiguration.java b/mongodb/querydsl/src/main/java/example/springdata/mongodb/reactive/ApplicationConfiguration.java
new file mode 100644
index 00000000..df9eb1a7
--- /dev/null
+++ b/mongodb/querydsl/src/main/java/example/springdata/mongodb/reactive/ApplicationConfiguration.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.reactive;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Configuration to connect to MongoDB using a {@link com.mongodb.reactivestreams.client.MongoClient}.
+ * Enables Spring Data repositories for MongoDB.
+ *
+ * @author Christoph Strobl
+ */
+@SpringBootApplication
+class ApplicationConfiguration {}
diff --git a/mongodb/querydsl/src/main/java/example/springdata/mongodb/reactive/ReactiveCustomerQuerydslRepository.java b/mongodb/querydsl/src/main/java/example/springdata/mongodb/reactive/ReactiveCustomerQuerydslRepository.java
new file mode 100644
index 00000000..387c74b5
--- /dev/null
+++ b/mongodb/querydsl/src/main/java/example/springdata/mongodb/reactive/ReactiveCustomerQuerydslRepository.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.reactive;
+
+import example.springdata.mongodb.Customer;
+
+import org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+
+/**
+ * Reactive Querydsl supporting repository interface to manage {@link Customer} instances.
+ *
+ * @author Christoph Strobl
+ */
+interface ReactiveCustomerQuerydslRepository
+ extends ReactiveCrudRepository, ReactiveQuerydslPredicateExecutor {
+
+}
diff --git a/mongodb/querydsl/src/main/java/example/springdata/mongodb/sync/ApplicationConfiguration.java b/mongodb/querydsl/src/main/java/example/springdata/mongodb/sync/ApplicationConfiguration.java
new file mode 100644
index 00000000..eea5a9ed
--- /dev/null
+++ b/mongodb/querydsl/src/main/java/example/springdata/mongodb/sync/ApplicationConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.sync;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import com.mongodb.MongoClient;
+
+/**
+ * Configuration to connect to MongoDB using a {@link MongoClient}.
+ * Enables Spring Data repositories for MongoDB.
+ *
+ * @author Christoph Strobl
+ */
+@SpringBootApplication
+class ApplicationConfiguration {}
diff --git a/mongodb/querydsl/src/main/java/example/springdata/mongodb/sync/CustomerQuerydslRepository.java b/mongodb/querydsl/src/main/java/example/springdata/mongodb/sync/CustomerQuerydslRepository.java
new file mode 100644
index 00000000..7d6a22c9
--- /dev/null
+++ b/mongodb/querydsl/src/main/java/example/springdata/mongodb/sync/CustomerQuerydslRepository.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.sync;
+
+import example.springdata.mongodb.Customer;
+
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Sync Querydsl supporting repository interface to manage {@link Customer} instances.
+ *
+ * @author Christoph Strobl
+ */
+interface CustomerQuerydslRepository extends CrudRepository, QuerydslPredicateExecutor {
+
+}
diff --git a/mongodb/querydsl/src/test/java/example/springdata/mongodb/reactive/ReactiveCustomerRepositoryTests.java b/mongodb/querydsl/src/test/java/example/springdata/mongodb/reactive/ReactiveCustomerRepositoryTests.java
new file mode 100644
index 00000000..078db80f
--- /dev/null
+++ b/mongodb/querydsl/src/test/java/example/springdata/mongodb/reactive/ReactiveCustomerRepositoryTests.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.reactive;
+
+import static org.assertj.core.api.Assertions.*;
+
+import example.springdata.mongodb.Customer;
+import example.springdata.mongodb.QCustomer;
+import reactor.test.StepVerifier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author Christoph Strobl
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class ReactiveCustomerRepositoryTests {
+
+ @Autowired ReactiveCustomerQuerydslRepository repository;
+ @Autowired MongoOperations operations;
+
+ Customer dave, oliver, carter;
+
+ @Before
+ public void setUp() {
+
+ repository.deleteAll().as(StepVerifier::create).verifyComplete();
+
+ dave = new Customer("Dave", "Matthews");
+ oliver = new Customer("Oliver August", "Matthews");
+ carter = new Customer("Carter", "Beauford");
+
+ repository.save(dave).then().as(StepVerifier::create).verifyComplete();
+ repository.save(oliver).then().as(StepVerifier::create).verifyComplete();
+ repository.save(carter).then().as(StepVerifier::create).verifyComplete();
+ }
+
+ @Test
+ public void findAllByPredicate() {
+
+ repository.findAll(QCustomer.customer.lastname.eq("Matthews")) //
+ .collectList() //
+ .as(StepVerifier::create) //
+ .assertNext(it -> assertThat(it).containsExactlyInAnyOrder(dave, oliver)) //
+ .verifyComplete();
+ }
+
+}
diff --git a/mongodb/querydsl/src/test/java/example/springdata/mongodb/sync/CustomerRepositoryTests.java b/mongodb/querydsl/src/test/java/example/springdata/mongodb/sync/CustomerRepositoryTests.java
new file mode 100644
index 00000000..cd9b75dd
--- /dev/null
+++ b/mongodb/querydsl/src/test/java/example/springdata/mongodb/sync/CustomerRepositoryTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example.springdata.mongodb.sync;
+
+import static org.assertj.core.api.Assertions.*;
+
+import example.springdata.mongodb.Customer;
+import example.springdata.mongodb.QCustomer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.mongodb.core.MongoOperations;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * @author Christoph Strobl
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class CustomerRepositoryTests {
+
+ @Autowired CustomerQuerydslRepository repository;
+ @Autowired MongoOperations operations;
+
+ Customer dave, oliver, carter;
+
+ @Before
+ public void setUp() {
+
+ repository.deleteAll();
+
+ dave = repository.save(new Customer("Dave", "Matthews"));
+ oliver = repository.save(new Customer("Oliver August", "Matthews"));
+ carter = repository.save(new Customer("Carter", "Beauford"));
+ }
+
+ @Test
+ public void findAllByPredicate() {
+ assertThat(repository.findAll(QCustomer.customer.lastname.eq("Matthews"))).containsExactlyInAnyOrder(dave, oliver);
+ }
+
+}
diff --git a/mongodb/querydsl/src/test/resources/application.properties b/mongodb/querydsl/src/test/resources/application.properties
new file mode 100644
index 00000000..c59a689b
--- /dev/null
+++ b/mongodb/querydsl/src/test/resources/application.properties
@@ -0,0 +1,2 @@
+# Random port for embedded MongoDB
+spring.data.mongodb.port=0