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. Reactive Relational Database Connectivity Mark Paluch • Spring Data Project

    Lead, R2DBC Contributor • @mp911de
  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
  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
  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)
  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())); }
  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
  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
  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
  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
  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
  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()
  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)
  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()
  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);
  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))))
  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))))
  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
  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)))
  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())
  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())
  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
  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();
  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))
  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
  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
  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
  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
  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
  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(); }
  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();
  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
  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>
  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>
  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");
  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
  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
  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
  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
  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
  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
  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
  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!
  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
  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
  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
  46. Thank you. r2dbc.io @mp911de