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. Reactive API et base de données ? Driver Java v2

    X DevAPI (CompletableFuture) SqlClient ADBA JDBC Reactive Extension Reactive Driver
  2. 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
  3. Reactive Streams “ ” The purpose of Reactive Streams is

    to provide a standard for asynchronous stream processing with non-blocking backpressure.
  4. 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)
  5. 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> {}
  6. 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 +
  7. 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
  8. 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 !
  9. 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); }
  10. @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); }
  11. 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 :(