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

R2DBC = R2D2 + JDBC (enfin presque...)

R2DBC = R2D2 + JDBC (enfin presque...)

Présentation de R2DBC (Reactive Relational Database Connectivity) avec exemples utilisant Spring Data R2DBC.

Bruno Bonnin

April 13, 2022
Tweet

More Decks by Bruno Bonnin

Other Decks in Technology

Transcript

  1. R2DBC = R2D2 + JDBC (enfin presque...) Bruno Bonnin @_bruno_b_

  2. Rejoignez-nous: https://cbp.fr/nous-rejoindre Blog technique: https://cbp-group.github.io/ Et pleins d’autres !

  3. Reactive Relational Database Connectivity

  4. Reactive API et base de données ? Driver Java v2

    X DevAPI (CompletableFuture) SqlClient ADBA JDBC Reactive Extension Reactive Driver
  5. Définit une interface standard de programmation réactive basée sur les

    Reactive Streams, destinée aux interactions avec les bases de données relationnelles. Reactive Streams R2DBC SPI R2DBC Driver X
  6. Reactive Streams “ ” The purpose of Reactive Streams is

    to provide a standard for asynchronous stream processing with non-blocking backpressure.
  7. Publisher Subscriber 1. subscribe 3. request(n) / cancel 2. onSubscribe

    (subscription) 4. onNext(data 1) 5. onComplete / onError Reactive Streams API Subscription 4. onNext(data …) 4. onNext(data n)
  8. Implémentation avec Project Reactor // Publisher de 0 à 1

    élément public abstract class Mono<T> implements CorePublisher<T> {} Flux.just("Hello", "How", "Are", "You?") .doOnNext(System.out::println) // Data consumer .doOnError(exc -> System.err.println("Sniff… " + exc)) // Error consumer .doOnComplete(() -> System.out.println("Fini !!")) // Complete consumer .subscribe(); // Publisher de 0 à n éléments public abstract class Flux<T> implements CorePublisher<T> {}
  9. ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc : h2 : mem : ///robot_db");

    Function<Connection, Publisher<? extends Result>> results = connection -> connection .createStatement("SELECT * FROM robot") .execute(); Mono.from(connectionPublisher) .flatMapMany(results) .flatMap(res -> res.map((row, meta) -> row.get("name", String.class))) .doOnNext(System.out::println) .doOnError(exc -> System.out.println("Sniff..." + exc)) .doOnComplete(() -> System.out.println("FINI !")) .subscribe(); Et si on met tout ça ensemble, ça donne à peu près ça ! (la prochaine fois, j’essaie un titre encore plus long…) R2DBC Project Reactor + Reactive Streams +
  10. Spring Data R2DBC

  11. spring: r2dbc: url: r2dbc:postgresql://localhost:15432/robot_db username: king_of_salsa password: un_truc_hyper_compliqué_noté_qqpart Tout commence

    par un peu de conf…
  12. DatabaseClient databaseClient = DatabaseClient.create(connectionFactory); Flux<Robot> robots = databaseClient .sql("SELECT *

    FROM robot WHERE name = :name") .bind("name", name) .map(row -> Robot.builder() .name(row.get("name", String.class)) .movie(row.get("movie", String.class)) .build()) .all(); PAS MAL, PAS MAL… MAIS UN PEU BAS NIVEAU… DatabaseClient
  13. R2dbcEntityTemplate r2dbcEntityTemplate = … Flux<Robot> robots = r2dbcEntityTemplate .select(Robot.class) .from("robot")

    .matching(query(where("name").is(name))) .all(); Flux<Robot> robots = r2dbcEntityTemplate .select(query(where("name").is(name)), Robot.class); R2dbcEntityTemplate ON PROGRESSE, C’EST MIEUX !
  14. public interface RobotRepository extends ReactiveCrudRepository<Robot, Long> { Flux<Robot> findByName(String name);

    @Query("select distinct movie from robot") Flux<String> getMovies(); } Reactive***Repository ET MAINTENANT, CA MARCHE AVEC UNE BASE RELATIONNELLE ! @GetMapping("/robot") public Flux<Robot> find(@RequestParam String name) { return repository.findByName(name); }
  15. @Transactional public Mono<Void> create(Robot robot, Movie movie) { return robotRepository.save(robot)

    .then(movieRepository.save(movie)) .then(); } Et avec un zeste de transaction ! public Mono<Void> create(Robot robot, Movie movie) { TransactionalOperator rxtx = TransactionalOperator.create(reactiveTxManager ); return robotRepository.save(robot) .then(movieRepository.save(movie)) .then() .as(rxtx::transactional); }
  16. Ecosystème - Drivers

  17. None
  18. Écosystème - Clients

  19. En résumé… Qu’a-t-on vu ? - Initiative plus qu’intéressante pour

    standardiser l’accès aux bases de données relationnelles en mode réactif - Il y a aussi du Batch, des Entity Callbacks, de l’Observability, … - Support de la communauté (clients, drivers, …) - On peut faire du R2DBC sans aucun autre framework, mais ça va être un peu roots :) Mais il reste du boulot ! - Des frameworks en cours de mises à jour (Liquibase, …) - Spring : pas de support des relations dans les entités :(
  20. Merci ! Démo: https://github.com/bbonnin/intro-r2dbc