I have to re-implement a few back-end services and one of the main requirement is to make the whole flow reactive. Previously the services used hibernate with PostgreSQL so the mentioned connections were provided by the framework.
Since I have to keep the original DB and just change the service implementation I have to use r2dbc-postgresql. I couldn't find any resource about this topic, but my best guess is to do something similar what I would do with JDBC and introduce some new connection tables between my entities.
I am looking into something similar and have come to the same conclusion (1), since there is no support for relations in R2DBC. To migrate a one-to-many relation I first made the collection containing the "many" entities to @Transient in the "one" entity. Persisting the "one" entity is accomplished using the following steps in a reactive sequence:
In code it looks like this:
public <S extends Drawing> Mono<S> save(final S inDrawing) {
final List<Shape> theDrawingShapes = inDrawing.getShapes();
return Mono.defer(() -> {
return Flux.fromIterable(theDrawingShapes)
.log()
.flatMap(theDrawingShape -> {
/* Save the shapes contained in the drawing. */
if (theDrawingShape instanceof Circle) {
final Circle theUnsavedCircle = (Circle) theDrawingShape;
return mCircleRepository.save(theUnsavedCircle);
} else if (theDrawingShape instanceof Rectangle) {
final Rectangle theUnsavedRectangle = (Rectangle) theDrawingShape;
return mRectangleRepository.save(theUnsavedRectangle);
} else {
LOGGER.warn("Unrecognized entity type: {}",
theDrawingShape.getClass().getName());
return Mono.just(theDrawingShape);
}
})
/* Update the drawing, setting the shapes of the drawing to the saved shapes. */
.collectList()
.map(theSavedShapesList -> {
inDrawing.setShapes(new ArrayList<>(theSavedShapesList));
return inDrawing;
})
/* Save the drawing itself. */
.flatMap(theDrawing -> super.save(theDrawing))
.flatMap(theDrawing -> {
/* Save the relations between the drawing and the shapes of the drawing. */
return Flux.fromIterable(theDrawing.getShapes())
.flatMap(theDrawingShape -> {
final var theDrawingShapeRelation = new DrawingShapesRelation();
theDrawingShapeRelation.setDrawingId(theDrawing.getId());
theDrawingShapeRelation.setShapeId(theDrawingShape.getId());
theDrawingShapeRelation.setShapeType(theDrawingShape.getClass()
.getName());
return mDrawingShapesRelationRepository.save(theDrawingShapeRelation);
})
.collectList()
.map(theDrawingShapesRelationList -> theDrawing);
});
});
}
My conclusion this far is that unless you are certain that there are major gains to be made from switching to R2DBC, I would settle for using Spring Data JPA and executing calls to repositories in a separate thread using subscribeOn.
Good luck and happy coding!