{"id":88574,"date":"2019-02-18T19:00:56","date_gmt":"2019-02-18T17:00:56","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=88574"},"modified":"2019-02-18T12:23:52","modified_gmt":"2019-02-18T10:23:52","slug":"asynchronous-rdbms-access-spring-r2dbc","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html","title":{"rendered":"Asynchronous RDBMS access with Spring Data R2DBC"},"content":{"rendered":"<p>Not too long ago, a reactive variant of the JDBC driver was released. Known as R2DBC. It allows data to be streamed asynchronously to any endpoints that have subscribed to it. Using a reactive driver like R2DBC together with Spring WebFlux allows you to write a full application that handles receiving and sending of data asynchronously. In this post, we will focus on the database. From connecting to the database and then finally saving and retrieving data. To do this, we will be using Spring Data. As with all Spring Data modules, it provides us with out of the box configuration. Decreasing the amount of boilerplate code that we need to write to get our application setup. On top of that, it provides a layer upon the database driver that makes doing the simple tasks easier and the more difficult tasks a little less painful.<\/p>\n<p>For the content of this post, I am making use of a Postgres database. At the time of writing only Postgres, H2 and Microsoft SQL Server have their own implementations of R2DBC drivers.<\/p>\n<p>I have previously written two posts about reactive Spring Data libraries, one on <a href=\"https:\/\/lankydanblog.com\/2017\/07\/16\/a-quick-look-into-reactive-streams-with-spring-data-and-mongodb\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Mongo<\/a> and another about <a href=\"https:\/\/lankydanblog.com\/2017\/12\/11\/reactive-streams-with-spring-data-cassandra\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Cassandra (opens in a new tab)\">Cassandra<\/a>. You might have noticed that neither of these databases are RDBMS databases. Now there are other reactive drivers available for a long time (I wrote the Mongo post nearly 2 years ago) but at the time of writing a reactive driver for a RDBMS database is still a pretty new thing. This post will follow a similar format to those.<\/p>\n<p>Furthermore, I have also written a post about using <a href=\"https:\/\/www.javacodegeeks.com\/2018\/03\/doing-stuff-with-spring-webflux.html\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Spring WebFlux<\/a> which I mentioned in the introduction. Feel free to have a look at that if you are interested in producing a fully reactive web application.<\/p>\n<h3 class=\"wp-block-heading\">Dependencies<\/h3>\n<pre class=\"brush:xml\">\n&lt;dependencies&gt;\n  &lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter&lt;\/artifactId&gt;\n  &lt;\/dependency&gt;\n  &lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.data&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-data-r2dbc&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.0.M1&lt;\/version&gt;\n  &lt;\/dependency&gt;\n  &lt;dependency&gt;\n    &lt;groupId&gt;io.r2dbc&lt;\/groupId&gt;\n    &lt;artifactId&gt;r2dbc-postgresql&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.0.M6&lt;\/version&gt;\n  &lt;\/dependency&gt;\n  &lt;dependency&gt;\n    &lt;groupId&gt;io.projectreactor&lt;\/groupId&gt;\n    &lt;artifactId&gt;reactor-core&lt;\/artifactId&gt;\n  &lt;\/dependency&gt;\n&lt;\/dependencies&gt;\n\n&lt;repositories&gt;\n  &lt;repository&gt;\n    &lt;id&gt;repository.spring.milestone&lt;\/id&gt;\n    &lt;name&gt;Spring Milestone Repository&lt;\/name&gt;\n    &lt;url&gt;http:\/\/repo.spring.io\/milestone&lt;\/url&gt;\n  &lt;\/repository&gt;\n&lt;\/repositories&gt;\n<\/pre>\n<p>There are a few things to point out here.<\/p>\n<p>The more you use Spring Boot, the more you will get used to importing a single <code>spring-boot-starter<\/code> dependency for the cool thing that you want to do. For example, I hoped that there would have been a <code>spring-boot-starter-r2dbc<\/code> dependency, but unfortunately, there is not one. Yet. Simply put, this library is on the newer side and at the time of writing, does not have its own Spring Boot module that contains any dependencies it needs along with faster setup via auto-configuration. I am sure these things will come at some point and make setting up a R2DBC driver even easier.<\/p>\n<p>For now, we will need to fill in a few extra dependencies manually.<\/p>\n<p>Furthermore, the R2DBC libraries only have Milestone releases (more proof of them being new) so we need to make sure we bring in the Spring Milestone repository. I will probably need to update this post in the future when it gets a release version.<\/p>\n<h3 class=\"wp-block-heading\">Connecting to the database<\/h3>\n<p>Thanks to Spring Data doing a lot of the work for us, the only Bean that needs to be created manually is the <code>ConnectionFactory<\/code> that contains the database\u2019s connection details:<\/p>\n<pre class=\"brush:java\">\n@Configuration\n@EnableR2dbcRepositories\nclass DatabaseConfiguration(\n  @Value(\"\\${spring.data.postgres.host}\") private val host: String,\n  @Value(\"\\${spring.data.postgres.port}\") private val port: Int,\n  @Value(\"\\${spring.data.postgres.database}\") private val database: String,\n  @Value(\"\\${spring.data.postgres.username}\") private val username: String,\n  @Value(\"\\${spring.data.postgres.password}\") private val password: String\n) : AbstractR2dbcConfiguration() {\n\n  override fun connectionFactory(): ConnectionFactory {\n    return PostgresqlConnectionFactory(\n      PostgresqlConnectionConfiguration.builder()\n        .host(host)\n        .port(port)\n        .database(database)\n        .username(username)\n        .password(password).build()\n    )\n  }\n}\n<\/pre>\n<p>The first thing to notice here is the extension of <code>AbstractR2dbcConfiguration<\/code>. This class contains a load of Beans that we no longer need to manually create. Implementing <code>connectionFactory<\/code> is the only requirement of the class as it is required to create the <code>DatabaseClient<\/code> Bean. This sort of structure is typical of Spring Data modules so it feels quite familiar when trying out a different one. Furthermore, I\u2019d expect this manual configuration to be removed once auto-configuration is available and be solely driven via the <code>application.properties<\/code>.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>I have included the <code>port<\/code> property here, but if you have not played around with your Postgres configuration then you can rely on the default value of <code>5432<\/code>.<\/p>\n<p>The four properties: <code>host<\/code>, <code>database<\/code>, <code>username<\/code> and <code>password<\/code> defined by the <code>PostgresqlConnectionFactory<\/code> are the bare minimum to get it working. Any less and you will experience exceptions during startup.<\/p>\n<p>Using this configuration, Spring is able to connect to a running Postgres instance.<\/p>\n<p>The final piece of noteworthy information from this example is the use of <code>@EnableR2dbcRepositories<\/code>. This annotation instructs Spring to find any repository interfaces that extend Spring\u2019s <code>Repository<\/code> interface. This is used as the base interface for instrumenting Spring Data repositories. We will look at this a little closer in the next section. The main piece of information to take away from here is that you need to use the <code>@EnableR2dbcRepositories<\/code> annotation to fully leverage Spring Data\u2019s capabilities.<\/p>\n<h3 class=\"wp-block-heading\">Creating a Spring Data Repository<\/h3>\n<p>As touched on above, in this section we will look at adding a Spring Data Repository. These repositories are a nice feature of Spring Data, meaning that you don\u2019t need to write out a load of extra code to simply write a query. Unfortunately, at least for now, Spring R2DBC cannot infer queries in the same way that other Spring Data modules currently do (I am sure this will be added at some point). This means that you will need to use the <code>@Query<\/code> annotation and write the SQL by hand. Let\u2019s take a look:<\/p>\n<pre class=\"brush:sql\">\n@Repository\ninterface PersonRepository : R2dbcRepository&lt;Person, Int&gt; {\n\n  @Query(\"SELECT * FROM people WHERE name = $1\")\n  fun findAllByName(name: String): Flux&lt;Person&gt;\n\n  @Query(\"SELECT * FROM people WHERE age = $1\")\n  fun findAllByAge(age: Int): Flux&lt;Person&gt;\n}\n<\/pre>\n<p>This interface extends <code>R2dbcRepository<\/code>. This in turn extends <code>ReactiveCrudRepository<\/code> and then down to <code>Repository<\/code>. <code>ReactiveCrudRepository<\/code> provides the standard CRUD functions and from what I understand, <code>R2dbcRepository<\/code> does not provide any extra functions and is instead an interface created for better situational naming.<\/p>\n<p><code>R2dbcRepository<\/code> takes in two generic parameters, one being the entity class that it takes as input and produces as output. The second being the type of the Primary Key. Therefore in this situation, the <code>Person<\/code> class is being managed by the <code>PersonRepository<\/code> (makes sense) and the Primary Key field inside <code>Person<\/code> is an <code>Int<\/code>.<\/p>\n<p>The return types of functions in this class and the ones provided by <code>ReactiveCrudRepository<\/code> are <code>Flux<\/code> and <code>Mono<\/code> (not seen here). These are Project Reactor types that Spring makes use of as the default Reactive Stream types. <code>Flux<\/code> represents a stream of multiple elements whereas a <code>Mono<\/code> is a single result.<\/p>\n<p>Finally, as I mentioned before the example, each function is annotated with <code>@Query<\/code>. The syntax is quite straight forward, with the SQL being a string inside the annotation. The <code>$1<\/code> (<code>$2<\/code>, <code>$3<\/code>, etc\u2026 for more inputs) represents the value input into the function. Once you have done this, Spring will handle the rest and pass the input(s) into their respective input parameter, gather the results and map it to the repository\u2019s designated entity class.<\/p>\n<h3 class=\"wp-block-heading\">A very quick look at the entity<\/h3>\n<p>Not going to say much here but simply show the <code>Person<\/code> class used by the <code>PersonRepository<\/code>.<\/p>\n<pre class=\"brush:java\">\n@Table(\"people\")\ndata class Person(\n  @Id val id: Int? = null,\n  val name: String,\n  val age: Int\n)\n<\/pre>\n<p>Actually, there is one point to make here. <code>id<\/code> has been made nullable and provided a default value of <code>null<\/code> to allow Postgres to generate the next suitable value itself. If this is not nullable and an <code>id<\/code> value is provided, Spring will actually try to run an update instead of an insert upon saving. There are other ways around this, but I think this is good enough.<\/p>\n<p>This entity will map to the <code>people<\/code> table defined below:<\/p>\n<pre class=\"brush:sql\">\nCREATE TABLE people (\n  id SERIAL PRIMARY KEY, \n  name VARCHAR NOT NULL, \n  age INTEGER NOT NULL\n);\n<\/pre>\n<h3 class=\"wp-block-heading\">Seeing it all in action<\/h3>\n<p>Now let\u2019s have a look at it actually doing something. Below is some code that inserts a few records and retrieves them in a few different ways:<\/p>\n<pre class=\"brush:java\">\n@SpringBootApplication\nclass Application : CommandLineRunner {\n\n  @Autowired\n  private lateinit var personRepository: PersonRepository\n\n  override fun run(vararg args: String?) {\n    personRepository.saveAll(\n      listOf(\n        Person(name = \"Dan Newton\", age = 25),\n        Person(name = \"Laura So\", age = 23)\n      )\n    ).log().subscribe()\n    personRepository.findAll().subscribe { log.info(\"findAll - $it\") }\n    personRepository.findAllById(Mono.just(1)).subscribe { log.info(\"findAllById - $it\") }\n    personRepository.findAllByName(\"Laura So\").subscribe { log.info(\"findAllByName - $it\") }\n    personRepository.findAllByAge(25).subscribe { log.info(\"findAllByAge - $it\") }\n  }\n}\n<\/pre>\n<p>One thing I will mention about this code. There is a very real possibility that it executes without actually inserting or reading some of the records. But, when you think about it. It makes sense. Reactive applications are meant to do things asynchronously and therefore this application has started processing the function calls in different threads. Without blocking the main thread, these asynchronous processes might never fully execute. For this reason, there are some <code>Thread.sleep<\/code> calls in this code, but I removed them from the example to keep everything tidy.<\/p>\n<p>The output for running the code above would look something like the below:<\/p>\n<pre class=\"brush:bash\">\n2019-02-11 09:04:52.294  INFO 13226 --- [           main] reactor.Flux.ConcatMap.1                 : onSubscribe(FluxConcatMap.ConcatMapImmediate)\n2019-02-11 09:04:52.295  INFO 13226 --- [           main] reactor.Flux.ConcatMap.1                 : request(unbounded)\n2019-02-11 09:04:52.572  INFO 13226 --- [actor-tcp-nio-1] reactor.Flux.ConcatMap.1                 : onNext(Person(id=35, name=Dan Newton, age=25))\n2019-02-11 09:04:52.591  INFO 13226 --- [actor-tcp-nio-1] reactor.Flux.ConcatMap.1                 : onNext(Person(id=36, name=Laura So, age=23))\n2019-02-11 09:04:52.591  INFO 13226 --- [actor-tcp-nio-1] reactor.Flux.ConcatMap.1                 : onComplete()\n2019-02-11 09:04:54.472  INFO 13226 --- [actor-tcp-nio-2] com.lankydanblog.tutorial.Application    : findAll - Person(id=35, name=Dan Newton, age=25)\n2019-02-11 09:04:54.473  INFO 13226 --- [actor-tcp-nio-2] com.lankydanblog.tutorial.Application    : findAll - Person(id=36, name=Laura So, age=23)\n2019-02-11 09:04:54.512  INFO 13226 --- [actor-tcp-nio-4] com.lankydanblog.tutorial.Application    : findAllByName - Person(id=36, name=Laura So, age=23)\n2019-02-11 09:04:54.524  INFO 13226 --- [actor-tcp-nio-5] com.lankydanblog.tutorial.Application    : findAllByAge - Person(id=35, name=Dan Newton, age=25)<\/pre>\n<p>A few things to take away here:<\/p>\n<ul class=\"wp-block-list\">\n<li><code>onSubscribe<\/code> and <code>request<\/code> occur on the main thread where the <code>Flux<\/code> was called from. Only <code>saveAll<\/code> outputs this since it has included the <code>log<\/code> function. Adding this to the other calls would have lead to the same result of logging to the main thread.<\/li>\n<li>The execution contained within the subscribe function and the internal steps of the <code>Flux<\/code> are ran on separate threads.<\/li>\n<\/ul>\n<p>This is not anywhere close to a real representation of how you would use Reactive Streams in an actual application but hopefully demonstrates how to use them and gives a bit of insight into how they execute.<\/p>\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n<p>In conclusion, Reactive Streams have come to some RDBMS databases thanks to the R2DBC driver and Spring Data that builds a layer on top to make everything a bit tidier. By using Spring Data R2DBC we are able to create a connection to a database and start querying it without the need of to much code. Although Spring is already doing a lot for us, it could be doing more. Currently, it does not have Spring Boot auto-configuration support. Which is a bit annoying. But, I am sure that someone will get around to doing it soon and make everything even better than it already is.<\/p>\n<p>The code used in this post can be found on my <a href=\"https:\/\/github.com\/lankydan\/spring-data-r2dbc\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"GitHub (opens in a new tab)\">GitHub<\/a>.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>Published on Java Code Geeks with permission by Dan Newton, partner at our <a href=\"\/\/www.javacodegeeks.com\/join-us\/jcg\/\" target=\"_blank\" rel=\"noopener\">JCG program<\/a>. See the original article here: <a href=\"https:\/\/lankydanblog.com\/2019\/02\/16\/asynchronous-rdbms-access-with-spring-data-r2dbc\/\" target=\"_blank\" rel=\"noopener\">Asynchronous RDBMS access with Spring Data R2DBC<\/a><\/p>\n<p>Opinions expressed by Java Code Geeks contributors are their own.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Not too long ago, a reactive variant of the JDBC driver was released. Known as R2DBC. It allows data to be streamed asynchronously to any endpoints that have subscribed to it. Using a reactive driver like R2DBC together with Spring WebFlux allows you to write a full application that handles receiving and sending of data &hellip;<\/p>\n","protected":false},"author":12894,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[1208,1152,1714,30,854,321,1858],"class_list":["post-88574","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-kotlin","tag-postgres","tag-reactive-streams","tag-spring","tag-spring-boot","tag-spring-data","tag-spring-data-r2dbc"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Asynchronous RDBMS access with Spring Data R2DBC - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about RDBMS access? Check our article explaining how R2DBC allows you to write a full application that handles data asynchronously.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Asynchronous RDBMS access with Spring Data R2DBC - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about RDBMS access? Check our article explaining how R2DBC allows you to write a full application that handles data asynchronously.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-02-18T17:00:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Dan Newton\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@LankyDanDev\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Dan Newton\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html\"},\"author\":{\"name\":\"Dan Newton\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/00ad664c44d777ebfa4d984dcf2717e2\"},\"headline\":\"Asynchronous RDBMS access with Spring Data R2DBC\",\"datePublished\":\"2019-02-18T17:00:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html\"},\"wordCount\":1520,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Kotlin\",\"Postgres\",\"Reactive Streams\",\"Spring\",\"Spring Boot\",\"Spring Data\",\"Spring Data R2DBC\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html\",\"name\":\"Asynchronous RDBMS access with Spring Data R2DBC - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2019-02-18T17:00:56+00:00\",\"description\":\"Interested to learn about RDBMS access? Check our article explaining how R2DBC allows you to write a full application that handles data asynchronously.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/02\\\/asynchronous-rdbms-access-spring-r2dbc.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Asynchronous RDBMS access with Spring Data R2DBC\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/00ad664c44d777ebfa4d984dcf2717e2\",\"name\":\"Dan Newton\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b5024a6405bf07e14dacc299779fc0abded33b42a05190784776429e2c76435f?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b5024a6405bf07e14dacc299779fc0abded33b42a05190784776429e2c76435f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b5024a6405bf07e14dacc299779fc0abded33b42a05190784776429e2c76435f?s=96&d=mm&r=g\",\"caption\":\"Dan Newton\"},\"sameAs\":[\"https:\\\/\\\/lankydanblog.com\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/danknewton\\\/\",\"https:\\\/\\\/x.com\\\/LankyDanDev\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/dan-newton\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Asynchronous RDBMS access with Spring Data R2DBC - Java Code Geeks","description":"Interested to learn about RDBMS access? Check our article explaining how R2DBC allows you to write a full application that handles data asynchronously.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html","og_locale":"en_US","og_type":"article","og_title":"Asynchronous RDBMS access with Spring Data R2DBC - Java Code Geeks","og_description":"Interested to learn about RDBMS access? Check our article explaining how R2DBC allows you to write a full application that handles data asynchronously.","og_url":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-02-18T17:00:56+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Dan Newton","twitter_card":"summary_large_image","twitter_creator":"@LankyDanDev","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Dan Newton","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html"},"author":{"name":"Dan Newton","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/00ad664c44d777ebfa4d984dcf2717e2"},"headline":"Asynchronous RDBMS access with Spring Data R2DBC","datePublished":"2019-02-18T17:00:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html"},"wordCount":1520,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Kotlin","Postgres","Reactive Streams","Spring","Spring Boot","Spring Data","Spring Data R2DBC"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html","url":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html","name":"Asynchronous RDBMS access with Spring Data R2DBC - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2019-02-18T17:00:56+00:00","description":"Interested to learn about RDBMS access? Check our article explaining how R2DBC allows you to write a full application that handles data asynchronously.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2019\/02\/asynchronous-rdbms-access-spring-r2dbc.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Asynchronous RDBMS access with Spring Data R2DBC"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/00ad664c44d777ebfa4d984dcf2717e2","name":"Dan Newton","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/b5024a6405bf07e14dacc299779fc0abded33b42a05190784776429e2c76435f?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/b5024a6405bf07e14dacc299779fc0abded33b42a05190784776429e2c76435f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b5024a6405bf07e14dacc299779fc0abded33b42a05190784776429e2c76435f?s=96&d=mm&r=g","caption":"Dan Newton"},"sameAs":["https:\/\/lankydanblog.com\/","https:\/\/www.linkedin.com\/in\/danknewton\/","https:\/\/x.com\/LankyDanDev"],"url":"https:\/\/www.javacodegeeks.com\/author\/dan-newton"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/88574","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/12894"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=88574"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/88574\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=88574"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=88574"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=88574"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}