Repository navigation
docs: Add docs for R2DBC DAO - #2949
Vik Nikolova (vnikolova) wants to merge 12 commits into
Conversation
Documentation split out of the exposed-dao-r2dbc implementation PR (#2831) so that it can be reviewed in parallel: - Migration-Guide-DAO-JDBC-to-R2DBC.md: new guide, from swapping the dependency to the per-API differences (newSuspend, reference accessors, Flow-based referrers, attach()) - DAO-CRUD-Operations, DAO-Entity-definition, DAO-Relationships, DAO-Table-Types: R2DBC variants alongside the JDBC snippets - lib.topic: reusable experimental-preview warning with the @ExperimentalR2dbcDaoApi opt-in - hi.tree: the new guide in the migration section - Adding-dependencies.md: "Database access modules" now lists both DAO modules and warns against mixing them in one source set - README.md, exposed-version-catalog/README.md: exposed-dao-r2dbc rows, and the exposed-dao row now points at it - CLAUDE.md, .junie/guidelines.md, .claude/skills/fix-bug: the new module and its test module in the module lists and test commands The module it documents landed in main with #2831, so this no longer has to wait on that PR and can be merged on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| <toc-element topic="dao-entity-definition.md" accepts-web-file-names="dao-field-transformations.html"/> | ||
| <toc-element topic="dao-crud-operations.md"/> | ||
| <toc-element topic="dao-relationships.md"/> | ||
| <toc-element topic="migrating-from-jdbc-to-r2dbc-dao.md"/> |
There was a problem hiding this comment.
Minor (or just opinion): I was a bit surprised to see this page in this location. Thought it would be under Releases, like the other migration guide, since it's technically attached to a release. But I can understand it being here, if that was what was requested.
There was a problem hiding this comment.
That depends if the intention is to deprecate the JDBC DAO, then it would fit better under Releases. If the JDBC DAO API will remain alongside R2DBC DAO, then I believe this is the correct placement for the migration guide.
| [references](dao-relationships.md), [queries](dao-crud-operations.md), and [transactions](Transactions.md), | ||
| with APIs adapted for suspending database operations. | ||
|
|
||
| To use R2DBC DAO, replace the JDBC DAO dependency with `exposed-dao-r2dbc` and use the `suspendTransaction()` function |
There was a problem hiding this comment.
Not sure if it's implicit/obvious that this means switching driver dependencies too.
There was a problem hiding this comment.
Still don't think this is clear, especially since exposed-jdbc does actually provide suspendTransaction(). Users could easily argue that they should be able to use exposed-dao-r2dbc + exposed-jdbc/suspendTransaction.
|
|
||
| // returns all UserRatingWithOptionalUserEntity objects with this movie as film | ||
| val filmRatings = starWarsFilm.ratings | ||
| println(filmRatings) |
There was a problem hiding this comment.
It prints Flow object. Also toList() could be added on the line above
| {style="tip"} | ||
|
|
||
| When an update occurs, the `modified` column is populated with the current UTC time using the `nowUTC()` method. However, | ||
| the update only happens if the `modified` field has not already been set. This is checked by using `Entity.writeValues`, |
There was a problem hiding this comment.
writeValues is not available in r2dbc.
the values are stored in EntityCache:
/** Uncommitted column values, kept off the entity so a rollback drops exactly what this scope staged. */
private val staged = IdentityHashMap<Entity<*>, StagedValues>()| @@ -0,0 +1,30 @@ | |||
| package org.example.examples | |||
There was a problem hiding this comment.
Is this snipped dead code? I don't see any usages of it. Probably I'm wrong, but right now I can't find it in the docs.
There was a problem hiding this comment.
Hm it indeed seems like it's no referenced anywhere..
| in the same way you would get any other field: | ||
|
|
||
| ```kotlin | ||
| movie.director // returns a Director object |
There was a problem hiding this comment.
should be movie.director(), because it's invocable now
| You can then access this field on a `DirectorCompositeIDEntity` object, `director`: | ||
|
|
||
| ```kotlin | ||
| director.films // returns all StarWarsFilm objects that reference this director |
There was a problem hiding this comment.
also should be director.films()
|
Thank you for the thorough reviews Chantal Loncle (@bog-walk) and Oleg Babichev (@obabichevjb) 🙏 |
| [references](dao-relationships.md), [queries](dao-crud-operations.md), and [transactions](Transactions.md), | ||
| with APIs adapted for suspending database operations. | ||
|
|
||
| To use R2DBC DAO, replace the JDBC DAO dependency with `exposed-dao-r2dbc` and use the `suspendTransaction()` function |
There was a problem hiding this comment.
Still don't think this is clear, especially since exposed-jdbc does actually provide suspendTransaction(). Users could easily argue that they should be able to use exposed-dao-r2dbc + exposed-jdbc/suspendTransaction.
| The `.new()` function schedules the entity for insert in the transaction's cache. The insert is flushed when you | ||
| explicitly call the `flushCache()` function, when another statement is executed in the same transaction, or when the transaction is committed. | ||
|
|
||
| * With JDBC, the entity's ID and any database-generated columns are available when the function returns. |
There was a problem hiding this comment.
Technically no, depending on how "available when the function returns" reads.
It may seem this way to a naive user, because when they access these fields, the values will be successfully returned from the entity with no issues.
But technically (and it will be obvious if the user has a logger or statement interceptor enabled) what will happen is that the insert will be (quietly-ish) flushed in order to access the returned statement's generated values.
I think this should be made clear, but we can always fix/clarify later.
| The pending inserts are flushed when required by subsequent database operations or when the transaction commits. Call | ||
| `flushCache()` when you need to explicitly control when the pending inserts are sent to the database. | ||
|
|
||
| > The `new()` function exists in both JDBC and R2DBC DAO but its behavior differs. During migration, review every `new{}` |
There was a problem hiding this comment.
Still don't agree with this. The behavior of the 2 .new() methods doesn't actually differ. It's the behavior of the property getters that truly differs. So continuing to use old new() with r2dbc would cause no issue & would act the same if the user never attempts to access id or generated values immediate after.
I'd suggest something like:
Even though the
new()function exists in both JDBC and R2DBC DAO and both result in scheduled inserts, the behavior of the new entity's property getters differs. During migration, review everynew()call that expects the row or its generated ID to exist immediately. Continuing to usenew()in these cases will throw an exception and they should be replaced withnewSuspend().
Description
Worked on top of the existing/generated docs from the obabichev/r2dbc-dao-docs branch
tldrelement for API links, and labels for JDBC-only/R2DBC-only features.Preview on staging
Type of Change
Related Issues
EXPOSED-1086 Documentation for Enable usage of DAO approach with R2DBC