Reactive Relational Database Connectivity 2020

C5f6e8dffbb19acf405198c8fb917337?s=47 Mark Paluch
November 28, 2019

Reactive Relational Database Connectivity 2020

Summarizes the state of R2DBC in 2020

C5f6e8dffbb19acf405198c8fb917337?s=128

Mark Paluch

November 28, 2019
Tweet

Transcript

  1. 2.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive Programming • High-efficiency applications • Fundamentally non-blocking • No opinion on async • Key differentiators: (pull-push) back pressure, flow control 2
  2. 3.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Subscriber Publisher Subscribe Data Demand
  3. 4.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Subscriber Publisher Subscribe Data request(n)
  4. 5.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ WebFlux and WebClient 5 @GetMapping("/health") Mono<Health> compositeHealth() { return Mono.zip( webClient.get().uri("https://alpha-service/health") .retrieve().bodyToMono(Health.class), webClient.get().uri("https://bravo-service/health") .retrieve().bodyToMono(Health.class)) .map(t -> composite(t.getT1(), t.getT2())); }
  5. 6.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Roadblocks • Barriers to using Reactive everywhere • Data Access • MongoDB, Apache Cassandra, Redis • No Relational Database Access 6
  6. 7.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 7 A specification designed from the ground up for reactive programming https://r2dbc.io
  7. 8.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Dependencies • Reactive Streams • Java 8 8
  8. 9.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Design Principles • Embrace Reactive Types and Patterns • Non-blocking, all the way to the database • Documented specification • Shrink the driver SPI • Enable multiple "humane" APIs 9
  9. 10.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Driver SPI • JDBC: same API for humane API and inhumane SPI for alternative clients like JPA, jOOQ, Jdbi, etc. • API that users didn't like using and driver authors didn't like implementing • Duplicating effort implementing the same "humane" affordances like ? binding 10
  10. 11.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Driver SPI: ConnectionFactory 11 Publisher<Connection> create() ConnectionFactoryMetadata getMetadata()
  11. 12.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Driver SPI: Connection 12 Publisher<Void> beginTransaction() Publisher<Void> close() Publisher<Void> commitTransaction() Batch createBatch() Publisher<Void> createSavepoint(String name) Statement createStatement(String sql) Publisher<Void> releaseSavepoint(String name) Publisher<Void> rollbackTransaction() Publisher<Void> rollbackTransactionToSavepoint(String name) Publisher<Void> setTransactionIsolationLevel(IsolationLevel isolationLevel)
  12. 13.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Driver SPI: Statement 13 Statement add() Statement bind(String name, Object value) Statement bind(int index, Object value) Statement bindNull(String name, Class<?> type) Statement bindNull(int index, Class<?> type) Statement returnGeneratedValues(String… columnNames) Publisher<Result> execute()
  13. 14.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Driver SPI: Result and Row 14 Publisher<Integer> getRowsUpdated() Publisher<T> map(BiFunction<Row, RowMetadata, ? extends T> f) T get(String identifier, Class<T> type); Object get(String identifier); T get(int index, Class<T> type); Object get(int index);
  14. 15.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Simple Select 15 Publisher<String> values = connectionFactory.create() .flatMapMany(conn -> conn.createStatement("SELECT value FROM test") .execute() .flatMap(result -> result.map((row, metadata) -> row.get("value", 
 String.class))))
  15. 16.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Transactional Update 16 Publisher<Result> results = connectionFactory.create() .flatMapMany(conn -> conn.beginTransaction() .thenMany(conn.createStatement("INSERT INTO test VALUES($1)") .bind("$1", 100).add() .bind("$1", 200).execute()) .delayUntil(p -> conn.commitTransaction()) .onErrorResume(t -> conn.rollbackTransaction().then(Mono.error(t))))
  16. 17.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Great! But a Bit Verbose. • Minimal set of implementation specific operations • Definitely usable, but very verbose and prone to errors • Explicit transaction management is analogous to try-catch- finally-try-catch in JDBC • We need a "humane" client API. In fact we need many humane client APIs! 17
  17. 18.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ R2DBC Client 18 Flux<String> values = r2dbc.withHandle(handle -> handle.select("SELECT value FROM test") .mapRow(row -> row.get("value", String.class)))
  18. 19.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Parametrized Statement 19 Flux<Integer> updatedRows = r2dbc.withHandle(handle -> handle.createUpdate("INSERT INTO test VALUES($1, $2)") .bind("$1", 100).bind("$2", 200).add() .bind("$1", 300).bind("$2", 400).execute())
  19. 20.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Transactional Update 20 Flux<Integer> updatedRows = r2dbc.inTransaction(handle -> handle.createUpdate("INSERT INTO test VALUES($1, $2)") .bind("$1", 100).bind("$2", 200).add() .bind("$1", 300).bind("$2", 400).execute())
  20. 21.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Data R2DBC
  21. 22.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Data R2DBC 22 DatabaseClient client = DatabaseClient.create(connectionFactory); Flux<Person> rows = client .execute("SELECT * FROM person WHERE name = :name") .bind("name", "John Doe") .as(Person.class) .fetch() .all();
  22. 23.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ R2DBC Repositories 23 interface CustomerRepository extends ReactiveCrudRepository<Customer, Long> { @Query("SELECT * FROM … WHERE lastname = :lastname") Flux<Customer> findByLastname(String lastname); } repository.findByLastname("Matthews") .doOnEach(c -> System.out.println(c.firstname))
  23. 24.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Data R2DBC • Functional-reactive declaration of data access • Fluent API • Support for Transactions • Named parameter support (Dialect-aware) • Repositories • Kotlin Coroutines extensions 24
  24. 25.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Demo
  25. 26.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Atomic Operations • Application and Database transactions • Classic implementations Thread-bound 26
  26. 27.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive Transactions • Application and Database transactions • Pattern is still correct 27
  27. 28.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive Transactions • Application and Database transactions • Pattern is still correct • Bind transactional state to Subscription • Reactor Context 28
  28. 29.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Reactive Transactions 29 PersonRepository people; AddressRepository addresses; @Transactional Mono<Void> savePerson(Person person, Address address) { return people.save(person) .then(addresses.save(address)).then(); }
  29. 30.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Programmatic Reactive Transactions 30 PersonRepository people; AddressRepository addresses; R2dbcTransactionManager txManager; TransactionalOperator rxtx = TransactionalOperator.create(txManager); Mono<Void> saved = people.save(person) .then(addresses.save(address)) .as(rxtx::transactional).then();
  30. 31.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting Started with R2DBC • Available from Maven Central • start.spring.io 31
  31. 32.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting Started with R2DBC 32 <dependencyManagement> <dependencies> <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-bom</artifactId> <version>Arabba-SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-h2</artifactId> </dependency> </dependencies>
  32. 33.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting Started with R2DBC 33 <dependencyManagement> <dependencies> <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-bom</artifactId> <version>Arabba-SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>io.r2dbc</groupId> <artifactId>r2dbc-h2</artifactId> </dependency> </dependencies>
  33. 34.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ R2DBC Connection URL 34 r2dbc:pool:postgresql://localhost:5432/database?key=value ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:postgresql://myhost/database? driver=foo");
  34. 35.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Boot Starter for R2DBC • ConnectionFactory configuration • R2DBC TransactionManager • Embedded H2 support • Actuator integration • Schema.sql and Data.sql support • @DataR2dbcTest 35
  35. 36.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 36
  36. 37.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ R2DBC Ecosystem
  37. 38.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ R2DBC Ecosystem • Specification document • R2DBC SPI • R2DBC Proxy • Connection Pooling • Client Implementations • Spring Data R2DBC • r2dbc-client • Kotysa • Drivers • Google Cloud Spanner • H2 • Microsoft SQL Server • MySQL Driver (r2dbc-mysql, jasync-sql) • MariaDB • PostgreSQL • SAP Hana 38
  38. 39.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Planned R2DBC Clients • MyBatis (#1444) • JDBI (#1454) • jOOQ (#6298) • Querydsl (#2468) • Helidon (#581) • Liquibase (CORE-3419) • Flyway (#2502) • Exposed (#456) • Testcontainers (#1003) • Go vote for a client you want to see happen. 39
  39. 40.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Planned R2DBC Drivers • MariaDB (alpha-state by MariaDB Inc.) • Firebird (Jaybird) investigating • Oracle investigating • DB2 foundation in the works (started with a vert.x driver first) • Ask your vendor! 40
  40. 41.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Non-blocking SQL Database Endeavours • Various individual driver projects (NDBC, Jasync, Vert.x, …) • Hibernate Rx • ADBA: Asynchronous Database API • OJDBC 20 with Reactive Extensions • Oracle looking into R2DBC 41
  41. 42.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Wrap up!
  42. 43.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What Can You Do Today? • End-to-end reactive non-blocking database communication • Batching • BLOB/CLOB • Extensive Type Conversion • Savepoints • Transactions • Leveraging Database-specific features • ServiceLoader-based Driver discovery • Connection URLs • Categorized exceptions (Bad grammar, Data integrity violation, …) 43
  43. 44.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ R2DBC Roadmap • Started as experiment in early 2018 • Available as 0.8.0 SR2 • 0.9.0: Stored Procedures, Extended transaction spec, EventProvider 44
  44. 45.

    Unless otherwise indicated, these slides are © 2013-2019 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Resources • Website
 https://r2dbc.io • Twitter
 @r2dbc • GitHub
 https://github.com/r2dbc • Mailing List
 https://groups.google.com/forum/ #!forum/r2dbc • Monthly Call
 1st Friday of Month 
 0630 PT/0930 ET/1530 CET 45