Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive Relational Database Connectivity 2020

Mark Paluch
November 28, 2019

Reactive Relational Database Connectivity 2020

Summarizes the state of R2DBC in 2020

Mark Paluch

November 28, 2019
Tweet

More Decks by Mark Paluch

Other Decks in Programming

Transcript

  1. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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