|
1 | 1 | image:https://spring.io/badges/spring-data-r2dbc/snapshot.svg["Spring Data R2DBC", link="https://spring.io/projects/spring-data-r2dbc#learn"]
|
2 | 2 |
|
3 |
| -image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-r2dbc%2Fmaster&subject=master["Spring Data R2DBC", link="https://jenkins.spring.io/view/SpringData/job/spring-data-r2dbc/"] |
4 |
| - |
5 |
| -= Spring Data R2DBC |
| 3 | += Spring Data R2DBC image:https://jenkins.spring.io/buildStatus/icon?job=spring-data-r2dbc%2Fmaster&subject=Build[link=https://jenkins.spring.io/view/SpringData/job/spring-data-r2dbc/] https://gitter.im/spring-projects/spring-data[image:https://badges.gitter.im/spring-projects/spring-data.svg[Gitter]] |
6 | 4 |
|
7 | 5 | The primary goal of the https://projects.spring.io/spring-data[Spring Data] project is to make it easier to build Spring-powered applications that use data access technologies. *Spring Data R2DBC* offers the popular Repository abstraction based on https://r2dbc.io[R2DBC].
|
8 | 6 |
|
9 | 7 | R2DBC is the abbreviation for https://github.com/r2dbc/[Reactive Relational Database Connectivity], an incubator to integrate relational databases using a reactive driver.
|
10 | 8 |
|
11 |
| -The state of R2DBC is incubating to evaluate how an reactive integration could look like. To get started, you need a R2DBC driver first. |
12 |
| - |
13 | 9 | == This is NOT an ORM
|
14 | 10 |
|
15 |
| -Spring Data R2DBC does not try to be an ORM. |
16 |
| -Instead it is more of a construction kit for your personal reactive relational data access component that you can define the way you like or need it. |
| 11 | +Spring Data R2DBC aims at being conceptually easy. In order to achieve this it does NOT offer caching, lazy loading, write behind or many other features of ORM frameworks. This makes Spring Data R2DBC a simple, limited, opinionated object mapper. |
17 | 12 |
|
18 |
| -== Maven Coordinates |
| 13 | +== Features |
19 | 14 |
|
20 |
| -[source,xml] |
21 |
| ----- |
22 |
| -<dependency> |
23 |
| - <groupId>org.springframework.data</groupId> |
24 |
| - <artifactId>spring-data-r2dbc</artifactId> |
25 |
| - <version>1.0.0.BUILD-SNAPSHOT</version> |
26 |
| -</dependency> |
27 |
| ----- |
| 15 | +* Spring configuration support using Java based `@Configuration` classes. |
| 16 | +* Annotation based mapping metadata. |
| 17 | +* Automatic implementation of Repository interfaces including support. |
| 18 | +* Support for Reactive Transactions |
| 19 | +* Schema and data initialization utilities. |
28 | 20 |
|
| 21 | +== Code of Conduct |
29 | 22 |
|
30 |
| -== DatabaseClient |
| 23 | +This project is governed by the link:CODE_OF_CONDUCT.adoc[Spring Code of Conduct]. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to [email protected]. |
31 | 24 |
|
32 |
| -All functionality is encapsulated in `DatabaseClient` which is the entry point for applications that wish to integrate with relational databases using reactive drivers: |
| 25 | +== Getting Started |
33 | 26 |
|
34 |
| -[source,java] |
35 |
| ----- |
36 |
| -PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder() |
37 |
| - .host(…) |
38 |
| - .database(…) |
39 |
| - .username(…) |
40 |
| - .password(…).build()); |
| 27 | +Here is a quick teaser of an application using Spring Data Repositories in Java: |
41 | 28 |
|
42 |
| -DatabaseClient databaseClient = DatabaseClient.create(connectionFactory); |
| 29 | +[source,java] |
43 | 30 | ----
|
| 31 | +public interface PersonRepository extends CrudRepository<Person, Long> { |
44 | 32 |
|
45 |
| -The client API provides covers the following features: |
46 |
| - |
47 |
| -* Execution of generic SQL and consumption of update count/row results. |
48 |
| -* Generic `SELECT` with paging and ordering. |
49 |
| -* `SELECT` of mapped objects with paging and ordering. |
50 |
| -* Generic `INSERT` with parameter binding. |
51 |
| -* `INSERT` of mapped objects. |
52 |
| -* Parameter binding using the native syntax. |
53 |
| -* Result consumption: Update count, unmapped (`Map<String, Object>`), mapped to entities, extraction function. |
54 |
| -* Reactive repositories using `@Query` annotated methods. |
55 |
| -* Transaction Management. |
56 |
| - |
57 |
| -=== Examples executing generic SQL statements |
| 33 | + @Query("SELECT * FROM person WHERE lastname = :lastname") |
| 34 | + Flux<Person> findByLastname(String lastname); |
58 | 35 |
|
59 |
| -[source,java] |
60 |
| ----- |
61 |
| -Mono<Integer> count = databaseClient.execute() |
62 |
| - .sql("INSERT INTO legoset (id, name, manual) VALUES($1, $2, $3)") |
63 |
| - .bind("$1", 42055) |
64 |
| - .bind("$2", "Description") |
65 |
| - .bindNull("$3", Integer.class) |
66 |
| - .fetch() |
67 |
| - .rowsUpdated(); |
68 |
| -
|
69 |
| -Flux<Map<String, Object>> rows = databaseClient.execute() |
70 |
| - .sql("SELECT id, name, manual FROM legoset") |
71 |
| - .fetch() |
72 |
| - .all(); |
73 |
| -
|
74 |
| -Flux<Long> result = db.execute() |
75 |
| - .sql("SELECT txid_current();") |
76 |
| - .map((r, md) -> r.get(0, Long.class)) |
77 |
| - .all(); |
78 |
| ----- |
| 36 | + @Query("SELECT * FROM person WHERE firstname LIKE :lastname") |
| 37 | + Flux<Person> findByFirstnameLike(String firstname); |
| 38 | +} |
79 | 39 |
|
80 |
| -=== Examples selecting data |
| 40 | +@Service |
| 41 | +public class MyService { |
81 | 42 |
|
82 |
| -[source,java] |
83 |
| ----- |
| 43 | + private final PersonRepository repository; |
84 | 44 |
|
85 |
| -Flux<Map<String, Object>> rows = databaseClient.select() |
86 |
| - .from("legoset") |
87 |
| - .orderBy(Sort.by(desc("id"))) |
88 |
| - .fetch() |
89 |
| - .all(); |
90 |
| -
|
91 |
| -Flux<LegoSet> rows = databaseClient.select() |
92 |
| - .from("legoset") |
93 |
| - .orderBy(Sort.by(desc("id"))) |
94 |
| - .as(LegoSet.class) |
95 |
| - .fetch() |
96 |
| - .all(); |
97 |
| ----- |
| 45 | + public MyService(PersonRepository repository) { |
| 46 | + this.repository = repository; |
| 47 | + } |
98 | 48 |
|
99 |
| -=== Examples inserting data |
| 49 | + public void doWork() { |
100 | 50 |
|
101 |
| -[source,java] |
102 |
| ----- |
103 |
| -Flux<Integer> ids = databaseClient.insert() |
104 |
| - .into("legoset") |
105 |
| - .value("id", 42055) |
106 |
| - .value("name", "Description") |
107 |
| - .nullValue("manual", Integer.class) |
108 |
| - .map((r, m) -> r.get("id", Integer.class) |
109 |
| - .all(); |
110 |
| -
|
111 |
| -Mono<Void> completion = databaseClient.insert() |
112 |
| - .into(LegoSet.class) |
113 |
| - .using(legoSet) |
114 |
| - .then(); |
115 |
| ----- |
| 51 | + repository.deleteAll().block(); |
116 | 52 |
|
117 |
| -=== Examples using reactive repositories |
| 53 | + Person person = new Person(); |
| 54 | + person.setFirstname("Mark"); |
| 55 | + person.setLastname("Paluch"); |
| 56 | + repository.save(person).block(); |
118 | 57 |
|
119 |
| -[source,java] |
120 |
| ----- |
121 |
| -interface LegoSetRepository extends ReactiveCrudRepository<LegoSet, Integer> { |
| 58 | + Flux<Person> lastNameResults = repository.findByLastname("Paluch"); |
| 59 | + Flux<Person> firstNameResults = repository.findByFirstnameLike("M%"); |
| 60 | + } |
| 61 | +} |
122 | 62 |
|
123 |
| - @Query("SELECT * FROM legoset WHERE name like $1") |
124 |
| - Flux<LegoSet> findByNameContains(String name); |
| 63 | +@Configuration |
| 64 | +@EnableR2dbcRepositories |
| 65 | +class ApplicationConfig extends AbstractR2dbcConfiguration { |
125 | 66 |
|
126 |
| - @Query("SELECT * FROM legoset WHERE manual = $1") |
127 |
| - Mono<LegoSet> findByManual(int manual); |
| 67 | + @Bean |
| 68 | + public ConnectionFactory connectionFactory() { |
| 69 | + return ConnectionFactories.get("r2dbc:h2:mem:///test?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"); |
| 70 | + } |
128 | 71 | }
|
129 | 72 | ----
|
130 | 73 |
|
131 |
| -=== Examples using transaction control |
| 74 | +=== Maven configuration |
132 | 75 |
|
133 |
| -All examples above run with auto-committed transactions. To get group multiple statements within the same transaction or |
134 |
| -control the transaction yourself, you need to use `TransactionalDatabaseClient`: |
| 76 | +Add the Maven dependency: |
135 | 77 |
|
136 |
| -[source,java] |
| 78 | +[source,xml] |
137 | 79 | ----
|
138 |
| -TransactionalDatabaseClient databaseClient = TransactionalDatabaseClient.create(connectionFactory); |
| 80 | +<dependency> |
| 81 | + <groupId>org.springframework.data</groupId> |
| 82 | + <artifactId>spring-data-r2dbc</artifactId> |
| 83 | + <version>${version}.RELEASE</version> |
| 84 | +</dependency> |
139 | 85 | ----
|
140 | 86 |
|
141 |
| -`TransactionalDatabaseClient` allows multiple flavors of transaction management: |
| 87 | +If you'd rather like the latest snapshots of the upcoming major version, use our Maven snapshot repository and declare the appropriate dependency version. |
142 | 88 |
|
143 |
| -* Participate in ongoing transactions and fall-back to auto-commit mode if there's no active transaction (default). |
144 |
| -* Group multiple statements in a managed transaction using `TransactionalDatabaseClient.inTransaction(…)`. |
145 |
| -* Application-controlled transaction management using `TransactionalDatabaseClient.beginTransaction()`/`commitTransaction()`/`rollbackTransaction()`. |
| 89 | +[source,xml] |
| 90 | +---- |
| 91 | +<dependency> |
| 92 | + <groupId>org.springframework.data</groupId> |
| 93 | + <artifactId>spring-data-r2dbc</artifactId> |
| 94 | + <version>${version}.BUILD-SNAPSHOT</version> |
| 95 | +</dependency> |
146 | 96 |
|
147 |
| -Participating in ongoing transactions does not require changes to your application code. Instead, a managed transaction must be hosted by your application container. Transaction control needs to happen there, as well. |
| 97 | +<repository> |
| 98 | + <id>spring-libs-snapshot</id> |
| 99 | + <name>Spring Snapshot Repository</name> |
| 100 | + <url>https://repo.spring.io/libs-snapshot</url> |
| 101 | +</repository> |
| 102 | +---- |
148 | 103 |
|
149 |
| -**Statement grouping** |
| 104 | +== Getting Help |
150 | 105 |
|
151 |
| -[source,java] |
152 |
| ----- |
153 |
| -Flux<Integer> rowsUpdated = databaseClient.inTransaction(db -> { |
154 |
| -
|
155 |
| - return db.execute().sql("INSERT INTO legoset (id, name, manual) VALUES($1, $2, $3)") // |
156 |
| - .bind(0, 42055) // |
157 |
| - .bind(1, "Description") // |
158 |
| - .bindNull("$3", Integer.class) // |
159 |
| - .fetch() |
160 |
| - .rowsUpdated(); |
161 |
| -}); |
162 |
| ----- |
| 106 | +Having trouble with Spring Data? We’d love to help! |
163 | 107 |
|
164 |
| -**Application-controlled transaction management** |
| 108 | +* Check the |
| 109 | +https://docs.spring.io/spring-data/r2dbc/docs/current/reference/html/[reference documentation], and https://docs.spring.io/spring-data/r2dbc/docs/current/api/[Javadocs]. |
| 110 | +* Learn the Spring basics – Spring Data builds on Spring Framework, check the https://spring.io[spring.io] web-site for a wealth of reference documentation. |
| 111 | +If you are just starting out with Spring, try one of the https://spring.io/guides[guides]. |
| 112 | +* If you are upgrading, check out the https://docs.spring.io/spring-data/r2dbc/docs/current/changelog.txt[changelog] for "`new and noteworthy`" features. |
| 113 | +* Ask a question - we monitor https://stackoverflow.com[stackoverflow.com] for questions tagged with https://stackoverflow.com/tags/spring-data[`spring-data-r2dbc`]. |
| 114 | +* Report bugs with Spring Data envers at https://github.com/spring-projects/spring-data-r2dbc/issues[github.com/spring-projects/spring-data-r2dbc/issues]. |
165 | 115 |
|
166 |
| -[source,java] |
167 |
| ----- |
168 |
| -Flux<Long> txId = databaseClient.execute().sql("SELECT txid_current();").exchange() |
169 |
| - .flatMapMany(it -> it.map((r, md) -> r.get(0, Long.class)).all()); |
| 116 | +== Reporting Issues |
170 | 117 |
|
171 |
| -Mono<Void> then = databaseClient.enableTransactionSynchronization(databaseClient.beginTransaction() // |
172 |
| - .thenMany(txId)) // |
173 |
| - .then(databaseClient.rollbackTransaction())); |
174 |
| ----- |
| 118 | +Spring Data uses GitHub as issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below: |
175 | 119 |
|
176 |
| -NOTE: Application-controlled transactions must be enabled with `enableTransactionSynchronization(…)`. |
| 120 | +* Before you log a bug, please search the |
| 121 | +https://github.com/spring-projects/spring-data-r2dbc/issues[issue tracker] to see if someone has already reported the problem. |
| 122 | +* If the issue doesn’t already exist, https://github.com/spring-projects/spring-data-r2dbc/issues/new[create a new issue]. |
| 123 | +* Please provide as much information as possible with the issue report, we like to know the version of Spring Data that you are using and JVM version. |
| 124 | +* If you need to paste code, or include a stack trace use Markdown +++```+++ escapes before and after your text. |
| 125 | +* If possible try to create a test-case or project that replicates the issue. Attach a link to your code or a compressed file containing your code. |
177 | 126 |
|
178 | 127 | == Building from Source
|
179 | 128 |
|
180 |
| -You don't need to build from source to use Spring Data R2DBC (binaries in https://repo.spring.io[repo.spring.io]), but if you want to try out the latest and greatest, Spring Data R2DBC can be easily built with the https://github.com/takari/maven-wrapper[maven wrapper]. You also need JDK 1.8. |
| 129 | +You don’t need to build from source to use Spring Data (binaries in https://repo.spring.io[repo.spring.io]), but if you want to try out the latest and greatest, Spring Data can be easily built with the https://github.com/takari/maven-wrapper[maven wrapper]. |
| 130 | +You also need JDK 1.8. |
181 | 131 |
|
182 |
| -[indent=0] |
| 132 | +[source,bash] |
183 | 133 | ----
|
184 |
| - $ ./mvnw clean install |
| 134 | + $ ./mvnw clean install |
185 | 135 | ----
|
186 | 136 |
|
187 | 137 | If you want to build with the regular `mvn` command, you will need https://maven.apache.org/run-maven/index.html[Maven v3.5.0 or above].
|
188 | 138 |
|
189 |
| -_Also see link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] if you wish to submit pull requests, and in particular please fill out the https://cla.pivotal.io/[Contributor's Agreement] before your first change._ |
190 |
| - |
191 |
| -== Running CI tasks locally |
| 139 | +_Also see link:CONTRIBUTING.adoc[CONTRIBUTING.adoc] if you wish to submit pull requests, and in particular please sign the https://cla.pivotal.io/sign/spring[Contributor’s Agreement] before your first change, is trivial._ |
192 | 140 |
|
193 |
| -Since this pipeline is purely Docker-based, it's easy to: |
| 141 | +=== Building reference documentation |
194 | 142 |
|
195 |
| -* Debug what went wrong on your local machine. |
196 |
| -* Test out a a tweak to your `test.sh` script before sending it out. |
197 |
| -* Experiment against a new image before submitting your pull request. |
| 143 | +Building the documentation builds also the project without running tests. |
198 | 144 |
|
199 |
| -All of these use cases are great reasons to essentially run what the CI server does on your local machine. |
200 |
| - |
201 |
| -IMPORTANT: To do this you must have Docker installed on your machine. |
202 |
| - |
203 |
| -1. `docker run -it --mount type=bind,source="$(pwd)",target=/spring-data-r2dbc-github -v /usr/bin/docker:/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock adoptopenjdk/openjdk8:latest /bin/bash` |
204 |
| -+ |
205 |
| -This will launch the Docker image and mount your source code at `spring-data-r2dbc-github`. |
206 |
| -+ |
207 |
| -2. `cd spring-data-r2dbc-github` |
208 |
| -+ |
209 |
| -Next, test everything from inside the container: |
210 |
| -+ |
211 |
| -3. `./mvnw -Pci,all-dbs clean dependency:list test -Dsort -B` (or whatever test configuration you must use) |
212 |
| - |
213 |
| -Since the container is binding to your source, you can make edits from your IDE and continue to run build jobs. |
| 145 | +[source,bash] |
| 146 | +---- |
| 147 | + $ ./mvnw clean install -Pdistribute |
| 148 | +---- |
214 | 149 |
|
215 |
| -NOTE: Docker containers can eat up disk space fast! From time to time, run `docker system prune` to clean out old images. |
| 150 | +The generated documentation is available from `target/site/reference/html/index.html`. |
216 | 151 |
|
217 |
| -== Contributing to Spring Data R2DBC |
| 152 | +== Examples |
218 | 153 |
|
219 |
| -Here are some ways for you to get involved in the community: |
| 154 | +* https://github.com/spring-projects/spring-data-examples/[Spring Data Examples] contains example projects that explain specific features in more detail. |
220 | 155 |
|
221 |
| -* Get involved with the Spring community by helping out on https://stackoverflow.com/questions/tagged/spring-data-r2dbc[Stackoverflow] by responding to questions and joining the debate. |
222 |
| -* Create https://github.com/spring-projects/spring-data-r2dbc[GitHub] tickets for bugs and new features and comment and vote on the ones that you are interested in. |
223 |
| -* Github is for social coding: if you want to write code, we encourage contributions through pull requests from https://help.github.com/forking/[forks of this repository]. If you want to contribute code this way, please reference a JIRA ticket as well, covering the specific issue you are addressing. |
224 |
| -* Watch for upcoming articles on Spring by https://spring.io/blog[subscribing] to spring.io. |
| 156 | +== License |
225 | 157 |
|
226 |
| -Before we accept a non-trivial patch or pull request we will need you to https://cla.pivotal.io/sign/spring[sign the Contributor License Agreement]. Signing the contributor’s agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. If you forget to do so, you'll be reminded when you submit a pull request. Active contributors might be asked to join the core team, and given the ability to merge pull requests. |
| 158 | +Spring Data R2DBC is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license]. |
0 commit comments