diff --git a/spring-5-data-reactive/pom.xml b/spring-5-data-reactive/pom.xml
index 8c16851de0..056fb37a52 100644
--- a/spring-5-data-reactive/pom.xml
+++ b/spring-5-data-reactive/pom.xml
@@ -1,9 +1,9 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
spring-5-data-reactive
- spring-5-data-reactive
+ spring-5-data-reactive
jar
@@ -49,11 +49,11 @@
${kotlin.version}
test
-
+
io.reactivex.rxjava2
rxjava
-
+
org.springframework
spring-test
@@ -68,6 +68,39 @@
de.flapdoodle.embed.mongo
test
+
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+
+
+
+ org.springframework
+ spring-tx
+ 5.2.0.M2
+
+
+
+ org.springframework.data
+ spring-data-r2dbc
+ 1.0.0.M2
+
+
+ io.r2dbc
+ r2dbc-h2
+ 0.8.0.M8
+
+
+ com.h2database
+ h2
+ 1.4.199
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
@@ -79,7 +112,7 @@
kotlin-maven-plugin
${kotlin-maven-plugin.version}
-
+
compile
@@ -123,7 +156,7 @@
-
+
org.apache.maven.plugins
maven-compiler-plugin
@@ -131,13 +164,13 @@
${java.version}
-
default-compile
none
-
default-testCompile
@@ -167,5 +200,21 @@
1.2.40
+
+
+ spring-snapshots
+ Spring Snapshots
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+
+
diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/R2dbcApplication.java b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/R2dbcApplication.java
new file mode 100644
index 0000000000..557b6ff42a
--- /dev/null
+++ b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/R2dbcApplication.java
@@ -0,0 +1,15 @@
+package com.baeldung.r2dbc;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@ComponentScan(basePackages = "com.baeldung.r2dbc")
+public class R2dbcApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(R2dbcApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/configuration/R2DBCConfiguration.java b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/configuration/R2DBCConfiguration.java
new file mode 100644
index 0000000000..17eac7fee2
--- /dev/null
+++ b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/configuration/R2DBCConfiguration.java
@@ -0,0 +1,21 @@
+package com.baeldung.r2dbc.configuration;
+
+import io.r2dbc.h2.H2ConnectionConfiguration;
+import io.r2dbc.h2.H2ConnectionFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration;
+import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories;
+
+@Configuration
+//@EnableR2dbcRepositories(basePackages = "com.baeldung.r2dbc.repository")
+public class R2DBCConfiguration extends AbstractR2dbcConfiguration {
+ @Bean
+ public H2ConnectionFactory connectionFactory() {
+ return new H2ConnectionFactory(
+ H2ConnectionConfiguration.builder()
+ .url("mem:testdb;DB_CLOSE_DELAY=-1;TRACE_LEVEL_FILE=4")
+ .username("sa")
+ .build());
+ }
+}
\ No newline at end of file
diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/model/Player.java b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/model/Player.java
new file mode 100644
index 0000000000..1926997e97
--- /dev/null
+++ b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/model/Player.java
@@ -0,0 +1,16 @@
+package com.baeldung.r2dbc.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.annotation.Id;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Player {
+ @Id
+ Integer id;
+ String name;
+ Integer age;
+}
\ No newline at end of file
diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/repository/PlayerRepository.java b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/repository/PlayerRepository.java
new file mode 100644
index 0000000000..33b653140e
--- /dev/null
+++ b/spring-5-data-reactive/src/main/java/com/baeldung/r2dbc/repository/PlayerRepository.java
@@ -0,0 +1,15 @@
+package com.baeldung.r2dbc.repository;
+
+import com.baeldung.r2dbc.model.Player;
+import org.springframework.data.r2dbc.repository.query.Query;
+import org.springframework.data.repository.reactive.ReactiveCrudRepository;
+import reactor.core.publisher.Flux;
+
+public interface PlayerRepository extends ReactiveCrudRepository {
+
+ @Query("select id, name, age from player where name = $1")
+ Flux findAllByName(String name);
+
+ @Query("select * from player where age = $1")
+ Flux findByAge(int age);
+}
\ No newline at end of file
diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/r2dbc/R2dbcApplicationIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/r2dbc/R2dbcApplicationIntegrationTest.java
new file mode 100644
index 0000000000..a31ef4458d
--- /dev/null
+++ b/spring-5-data-reactive/src/test/java/com/baeldung/r2dbc/R2dbcApplicationIntegrationTest.java
@@ -0,0 +1,125 @@
+package com.baeldung.r2dbc;
+
+
+import com.baeldung.r2dbc.model.Player;
+import com.baeldung.r2dbc.repository.PlayerRepository;
+import io.r2dbc.h2.H2ConnectionFactory;
+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.r2dbc.core.DatabaseClient;
+import org.springframework.test.context.junit4.SpringRunner;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Hooks;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class R2dbcApplicationIntegrationTest {
+
+
+ @Autowired
+ PlayerRepository playerRepository;
+
+ @Autowired
+ DatabaseClient client;
+
+ @Autowired
+ H2ConnectionFactory factory;
+
+
+ @Before
+ public void setup() {
+
+ Hooks.onOperatorDebug();
+
+ List statements = Arrays.asList(//
+ "DROP TABLE IF EXISTS player;",
+ "CREATE table player (id INT AUTO_INCREMENT NOT NULL, name VARCHAR2, age INT NOT NULL);");
+
+ statements.forEach(it -> client.execute() //
+ .sql(it) //
+ .fetch() //
+ .rowsUpdated() //
+ .as(StepVerifier::create) //
+ .expectNextCount(1) //
+ .verifyComplete());
+
+ }
+
+ @Test
+ public void whenDeleteAll_then0IsExpected() {
+
+
+ playerRepository.deleteAll()
+ .as(StepVerifier::create)
+ .expectNextCount(0)
+ .verifyComplete();
+ }
+
+ @Test
+ public void whenInsert6_then6AreExpected() {
+
+ insertPlayers();
+
+ playerRepository.findAll()
+ .as(StepVerifier::create)
+ .expectNextCount(6)
+ .verifyComplete();
+ }
+
+ @Test
+ public void whenSearchForCR7_then1IsExpected() {
+
+ insertPlayers();
+
+ playerRepository.findAllByName("CR7")
+ .as(StepVerifier::create)
+ .expectNextCount(1)
+ .verifyComplete();
+ }
+
+ @Test
+ public void whenSearchFor32YearsOld_then2AreExpected() {
+ insertPlayers();
+
+ playerRepository.findByAge(32)
+ .as(StepVerifier::create)
+ .expectNextCount(2)
+ .verifyComplete();
+ }
+
+ @Test
+ public void whenBatchHas2Operations_then2AreExpected() {
+ Mono.from(factory.create())
+ .flatMapMany(connection -> Flux.from(connection
+ .createBatch()
+ .add("select * from player")
+ .add("select * from player")
+ .execute()))
+ .as(StepVerifier::create)
+ .expectNextCount(2)
+ .verifyComplete();
+
+ }
+
+ private void insertPlayers() {
+ List players = Arrays.asList(
+ new Player(1, "Kaka", 37),
+ new Player(2, "Messi", 32),
+ new Player(3, "Mbappé", 20),
+ new Player(4, "CR7", 34),
+ new Player(5, "Lewandowski", 30),
+ new Player(6, "Cavani", 32)
+ );
+
+ playerRepository.saveAll(players).subscribe();
+ }
+}
+