diff --git a/benchmark/relational/pom.xml b/benchmark/relational/pom.xml
index cdb42af..8d08166 100644
--- a/benchmark/relational/pom.xml
+++ b/benchmark/relational/pom.xml
@@ -13,6 +13,10 @@
spring-data-benchmark-relational
Spring Data Benchmarks - Relational Microbenchmarks
+
+
+ 0.1.0.BUILD-SNAPSHOT
+
@@ -41,6 +45,28 @@
postgresql
+
+
+
+ org.springframework.boot.experimental
+ spring-boot-starter-data-r2dbc
+ ${spring-boot-data-r2dbc.version}
+
+
+
+ io.r2dbc
+ r2dbc-h2
+ 0.8.0.M8
+
+
+
+ io.r2dbc
+ r2dbc-postgresql
+ 0.8.0.M8
+
+
+
+
org.mockito
mockito-core
diff --git a/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/Book.java b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/Book.java
new file mode 100644
index 0000000..1b5ad1b
--- /dev/null
+++ b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/Book.java
@@ -0,0 +1,43 @@
+/*
+ * 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 org.springframework.data.microbenchmark.r2dbc;
+
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+import lombok.Value;
+import lombok.experimental.Wither;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.annotation.PersistenceConstructor;
+
+/**
+ * @author Oliver Drotbohm
+ */
+@Value
+@RequiredArgsConstructor(access = AccessLevel.PACKAGE, onConstructor = @__(@PersistenceConstructor))
+class Book {
+
+ @Wither(AccessLevel.PACKAGE) @Id Long id;
+ String title;
+ int pages;
+
+ public Book(String title, int pages) {
+
+ this.id = null;
+ this.title = title;
+ this.pages = pages;
+ }
+}
diff --git a/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcBenchmark.java b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcBenchmark.java
new file mode 100644
index 0000000..1ea478b
--- /dev/null
+++ b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcBenchmark.java
@@ -0,0 +1,105 @@
+/*
+ * 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 org.springframework.data.microbenchmark.r2dbc;
+
+import java.util.function.Function;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.infra.Blackhole;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.data.microbenchmark.common.AbstractMicrobenchmark;
+import org.springframework.data.r2dbc.core.DatabaseClient;
+
+import io.r2dbc.spi.Row;
+
+/**
+ * Benchmark for R2DBC and Spring Data R2DBC
+ *
+ * @author Oliver Drotbohm
+ */
+public class R2dbcBenchmark extends AbstractMicrobenchmark {
+
+ private static final String FIND_ALL_SQL = "SELECT id, title, pages FROM Book";
+ private static final String BY_TITLE_SQL = FIND_ALL_SQL + " where title = :title";
+
+ @Param({ /* "postgres", */ "h2-in-memory" /*, "h2" */ })
+ String profile;
+
+ private DatabaseClient operations;
+ private Function mapper;
+
+ private R2dbcBookRepository repository;
+
+ @Setup
+ public void setUp() {
+
+ R2dbcFixture fixture = new R2dbcFixture(profile);
+
+ ConfigurableApplicationContext context = fixture.getContext();
+
+ this.operations = context.getBean(DatabaseClient.class);
+ this.mapper = row -> new Book(row.get("id", Long.class), row.get("title", String.class), row.get("pages", Integer.class));
+
+ this.repository = context.getBean(R2dbcBookRepository.class);
+ }
+
+ @Benchmark
+ public void findByTitle(Blackhole sink) {
+
+ sink.consume(operations.execute(BY_TITLE_SQL) //
+ .bind("title", "title0") //
+ .map(mapper)
+ .one() //
+ .block());
+ }
+
+ @Benchmark
+ public void findAll(Blackhole sink) {
+
+ sink.consume(operations.execute(FIND_ALL_SQL) //
+ .map(mapper) //
+ .all() //
+ .collectList() //
+ .block());
+ }
+
+ @Benchmark
+ public void repositoryFindByTitle(Blackhole sink) {
+ sink.consume(repository.findByTitle("title0").block());
+ }
+
+ @Benchmark
+ public void repositoryFindTransactionalByTitle(Blackhole sink) {
+ sink.consume(repository.findTransactionalByTitle("title0").block());
+ }
+
+ @Benchmark
+ public void repositoryFindAll(Blackhole sink) {
+ sink.consume(repository.findAll().collectList().block());
+ }
+
+ public static void main(String[] args) {
+
+ new R2dbcFixture("postgres") //
+ .getContext() //
+ .getBean(R2dbcBookRepository.class) //
+ .findAll() //
+ .collectList() //
+ .block();
+ }
+}
diff --git a/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcBookRepository.java b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcBookRepository.java
new file mode 100644
index 0000000..55f8c69
--- /dev/null
+++ b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcBookRepository.java
@@ -0,0 +1,44 @@
+/*
+ * 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 org.springframework.data.microbenchmark.r2dbc;
+
+import org.springframework.data.r2dbc.repository.R2dbcRepository;
+import org.springframework.data.r2dbc.repository.query.Query;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+/**
+ * A repository for {@link Book} instances.
+ *
+ * @author Oliver Drotbohm
+ */
+interface R2dbcBookRepository extends R2dbcRepository {
+
+ static final String BY_TITLE = "SELECT id, title, pages FROM Book where title = :title";
+
+ @Transactional(propagation = Propagation.NOT_SUPPORTED)
+ Flux findAll();
+
+ @Query(BY_TITLE)
+ Mono findByTitle(String title);
+
+ @Transactional(readOnly = true)
+ @Query(BY_TITLE)
+ Mono findTransactionalByTitle(String title);
+}
diff --git a/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcFixture.java b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcFixture.java
new file mode 100644
index 0000000..40eecc2
--- /dev/null
+++ b/benchmark/relational/src/main/java/org/springframework/data/microbenchmark/r2dbc/R2dbcFixture.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 org.springframework.data.microbenchmark.r2dbc;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.r2dbc.R2dbcProperties;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.data.microbenchmark.FixtureUtils;
+import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;
+
+import io.r2dbc.spi.ConnectionFactory;
+import lombok.Getter;
+
+/**
+ * Test fixture for JDBC and Spring Data JDBC benchmarks.
+ *
+ * @author Oliver Drotbohm
+ */
+public class R2dbcFixture {
+
+ private final @Getter ConfigurableApplicationContext context;
+
+ public R2dbcFixture(String database) {
+
+ this.context = FixtureUtils.createContext(R2dbcApplication.class, "r2dbc", database);
+
+ R2dbcProperties properties = context.getBean(R2dbcProperties.class);
+ String platform = properties.getPlatform();
+
+ Resource schema = new ClassPathResource(String.format("schema-%s.sql", platform));
+ Resource data = new ClassPathResource(String.format("data-%s.sql", platform));
+
+ ResourceDatabasePopulator populator = new ResourceDatabasePopulator(schema, data);
+ populator.execute(context.getBean(ConnectionFactory.class)).block();
+ }
+
+
+ @SpringBootApplication (exclude = {
+ DataSourceAutoConfiguration.class
+ })
+ static class R2dbcApplication {}
+}
diff --git a/benchmark/relational/src/main/resources/application-h2-in-memory.properties b/benchmark/relational/src/main/resources/application-h2-in-memory.properties
index 7eecee5..09e4bd6 100644
--- a/benchmark/relational/src/main/resources/application-h2-in-memory.properties
+++ b/benchmark/relational/src/main/resources/application-h2-in-memory.properties
@@ -1,2 +1,3 @@
spring.datasource.platform=h2
+spring.r2dbc.platform=h2
diff --git a/benchmark/relational/src/main/resources/application-h2.properties b/benchmark/relational/src/main/resources/application-h2.properties
index 1e4cfa4..f977da2 100644
--- a/benchmark/relational/src/main/resources/application-h2.properties
+++ b/benchmark/relational/src/main/resources/application-h2.properties
@@ -4,3 +4,8 @@ spring.datasource.password=
spring.datasource.platform=h2
spring.datasource.initialization-mode=always
+spring.r2dbc.url=r2dbc:h2:tcp://localhost:9092/~/benchmark
+spring.r2dbc.username=sa
+spring.r2dbc.password=
+spring.r2dbc.platform=h2
+spring.r2dbc.initialization-mode=always
diff --git a/benchmark/relational/src/main/resources/application-postgres.properties b/benchmark/relational/src/main/resources/application-postgres.properties
index afd1d52..db931a0 100644
--- a/benchmark/relational/src/main/resources/application-postgres.properties
+++ b/benchmark/relational/src/main/resources/application-postgres.properties
@@ -2,3 +2,6 @@ spring.datasource.url=jdbc:postgresql://localhost:5432/benchmark
spring.datasource.platform=postgres
spring.datasource.initialization-mode=always
+spring.r2dbc.url=r2dbc:postgresql://localhost:5432/benchmark
+spring.r2dbc.platform=postgres
+spring.r2dbc.initialization-mode=always
\ No newline at end of file
diff --git a/benchmark/relational/src/main/resources/application-r2dbc.properties b/benchmark/relational/src/main/resources/application-r2dbc.properties
new file mode 100644
index 0000000..9273bdb
--- /dev/null
+++ b/benchmark/relational/src/main/resources/application-r2dbc.properties
@@ -0,0 +1,2 @@
+spring.data.jpa.repositories.enabled=false
+spring.data.jdbc.repositories.enabled=false