{"id":16696935,"url":"https://github.com/seratch/r2dbc-samples-in-scala","last_synced_at":"2025-04-10T02:52:12.856Z","repository":{"id":139894202,"uuid":"163092084","full_name":"seratch/r2dbc-samples-in-scala","owner":"seratch","description":"Demonstrates how to use R2DBC - Reactive Relational Database Connectivity in Scala","archived":false,"fork":false,"pushed_at":"2019-02-27T12:42:58.000Z","size":17,"stargazers_count":11,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T04:22:21.844Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seratch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-25T15:06:47.000Z","updated_at":"2022-11-21T00:09:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"ca7277dc-444b-414f-b1d1-d6e4191498b8","html_url":"https://github.com/seratch/r2dbc-samples-in-scala","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fr2dbc-samples-in-scala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fr2dbc-samples-in-scala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fr2dbc-samples-in-scala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seratch%2Fr2dbc-samples-in-scala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seratch","download_url":"https://codeload.github.com/seratch/r2dbc-samples-in-scala/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248147061,"owners_count":21055470,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-12T17:45:20.242Z","updated_at":"2025-04-10T02:52:12.841Z","avatar_url":"https://github.com/seratch.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# R2DBC First Example in Scala\n\n[![Build Status](https://travis-ci.org/seratch/r2dbc-samples-in-scala.svg?branch=master)](https://travis-ci.org/seratch/r2dbc-samples-in-scala)\n\nThis repository demonstrates how to use [R2DBC - Reactive Relational Database Connectivity](http://r2dbc.io/) in Scala.\n\nAs of Dec 2018, R2DBC is still under the development. Thus, there are still many limitations:\n\n* Supported RDBMS: PostgreSQL, H2, and MS SQL Server\n* CLOB/BLOB unsupported\n* No connection pooling\n\nIn this example, I use [`r2dbc-client`](https://github.com/r2dbc/r2dbc-client) which is the reference implementation of [`r2dbc-spi`](https://github.com/r2dbc/r2dbc-spi), the service provider interface. `r2dbc-client` heavily depends on [Reactor](https://projectreactor.io/), whereas the R2DBC SPI doesn't have any relatiojns with Reactor. The SPI relies on only [Reactive Streams](http://www.reactive-streams.org/). Thanks to the  thin SPI interface, it should be much easier to implement your own R2DBC clients than toilsome JDBC drivers.\n\nWhile working with `r2dbc-client`, you will see lots of [`Flux`](https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html)/[`Mono`](https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html) objects. As far as I know, Reactor is not so popular in the Scala world (The Scala community already has many other options to achieve the same goal). You may feel like \"What's `Flux`/`Mono`...? Do I need to learn ways to use it?\" Don't worry, be happy. You don't need to learn the details of it. They are just enriched `Publisher` objects in the context of Reactive Streams. So, if you're familiar with the `Publisher`, you can simply handle `Flux`/`Mono` as `Publisher`. Otherwise, I recommend transforming those types to your favorites such as [`Observable`](https://monix.io/docs/3x/reactive/observable.html) in [monix-reactive](https://monix.io/docs/3x/#monix-reactive), [`Stream` in fs2](https://fs2.io/guide.html), etc.\n\n# Getting Started\n\n## build.sbt\n\n`r2dbc-client` is always mandatory. In addition to that, you must have the necessary dialect, any of `r2dbc-h2`, `r2dbc-postgresql`, and `r2dbc-mssql`. Don't forget to have the `spring-milestone` resolver. R2DBC libraries are not available on the Maven Central yet.\n\n```scala\n// Minimum settings for R2DBC\nlazy val root = (project in file(\".\"))\n  .settings(\n    scalaVersion := \"2.12.8\",\n    resolvers += \"spring-milestone\" at \"https://repo.spring.io/milestone\",\n    libraryDependencies ++= Seq(\n      \"io.r2dbc\" % \"r2dbc-client\"     % \"1.0.0.M6\"  % Compile,\n      \"io.r2dbc\" % \"r2dbc-h2\"         % \"1.0.0.M6\"  % Compile,\n      \"io.r2dbc\" % \"r2dbc-postgresql\" % \"1.0.0.M6\"  % Compile\n    )\n  )\n\n// You can build Monix's Observable from Flux/Mono instantly\nlibraryDependencies += \"io.monix\" %% \"monix-reactive\" % \"3.0.0-RC2\" % Compile\n\n// If you need the ways to convert Flux/Mono to Scala Future\nlibraryDependencies += \"org.scala-lang.modules\" %% \"scala-java8-compat\" % \"0.9.0\" % Compile\n```\n\n## Code Example\n\nHere is a simple code example to run queries on H2 in-memory database. Apart from the part to build `io.r2dbc.client.R2dbc`, the exactly same code works for PostgreSQL. \n\nTo make the example simple, the code intentionally does blocking operations. Needless to say, you must NOT do the same in real application code. Follow the best practices to leverage the benefits of reactive / non-blocking model.\n\n```scala\nval config = io.r2dbc.h2.H2ConnectionConfiguration.builder().url(\"mem:sample1\").build()\nval r2dbc  = new io.r2dbc.client.R2dbc(new io.r2dbc.h2.H2ConnectionFactory(config))\n\n// Create the table beforehand\nr2dbc\n  // Don't use text type, R2DBC doesn't work with it as of Dec 2018\n  .withHandle(_.execute(\"create table sample (id bigint primary key, name varchar(100))\"))\n  .blockFirst() // Flux#blockFirst()\n\nval result: reactor.core.publisher.Flux[Sample] = {\n  // Insert three rows\n  val insertions: reactor.core.publisher.Flux[Integer] = r2dbc.inTransaction { handle =\u003e\n    val updates = handle.createUpdate(\"insert into sample (id, name) values ($1, $2)\")\n    updates.bind(\"$1\", 1).bind(\"$2\", \"Alice\").add()\n    updates.bind(\"$1\", 2).bind(\"$2\", \"Bob\").add()\n    updates.bind(\"$1\", 3).bindNull(\"$2\", classOf[String]).add()\n    updates.execute()\n  }\n  // Select all the rows descending order\n  val fetchingAll: reactor.core.publisher.Flux[Sample] = r2dbc.withHandle { handle =\u003e\n    handle.select(\"select id, name from sample order by id desc\").mapRow { row =\u003e\n      Sample(\n        id = Long.unbox(row.get(\"id\", classOf[java.lang.Long])),\n        name = Option(row.get(\"name\", classOf[String]))\n      )\n    }\n  }\n  // 'fetchingAll' will be executed after the completion of 'insertions'\n  insertions.thenMany(fetchingAll)\n}\n```\n\nTo work with `Publisher` more easily, you can use `Observable` from `monix-reactive`. Refer to [the Monix document](https://monix.io/docs/3x/reactive/observable.html) for details.\n\n```scala\n// simple example to run with monix-reactive\nimport monix.reactive.Observable\nval observable: Observable[Sample] = Observable.fromReactivePublisher(result)\n\n// Just for demonstration, intentionally does the blocking ops here\nimport monix.execution.Scheduler.Implicits.global\nval samples: Seq[Sample] = observable.toListL.runSyncUnsafe()\nsamples.map(_.id) should equal(Seq(3, 2, 1))\n```\n\n# References\n\n* [Reactive Streams](http://www.reactive-streams.org/)\n* [R2DBC Website](http://r2dbc.io/)\n* [R2DBC GitHub Organization](https://github.com/r2dbc)\n* [\"Reactive Relational Database Connectivity\" at SpringOne Platform 2018](https://www.youtube.com/watch?v=idApf9DMdfk)\n* [Project Reactor](https://projectreactor.io/)\n* [Reactor Flux javadoc](https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html)\n* [Monix Website](https://monix.io/)\n* [Monix Reactive - Observable](https://monix.io/docs/3x/reactive/observable.html)\n* [Monix Eval - Task](https://monix.io/docs/3x/eval/task.html)\n* [Monix Reactive](https://monix.io/docs/3x/#monix-reactive)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseratch%2Fr2dbc-samples-in-scala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseratch%2Fr2dbc-samples-in-scala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseratch%2Fr2dbc-samples-in-scala/lists"}