Как реализовать OneToMany, ManyToOne и ManyToMany с R2DB C в проекте, который ранее использовал JPA? - PullRequest
3 голосов
/ 30 января 2020

Мне нужно повторно внедрить несколько внутренних служб, и одно из главных требований - сделать весь поток реагирующим. Ранее сервисы использовали hibernate с PostgreSQL, поэтому упомянутые соединения были предоставлены платформой.

Поскольку мне нужно сохранить исходную БД и просто изменить реализацию службы, я должен использовать r2db c - postgresql. Я не смог найти какой-либо ресурс об этой топике c, но я предпочитаю сделать что-то похожее, что я сделал бы с JDB C, и ввести несколько новых таблиц соединений между моими сущностями.

  1. Это был бы правильный подход или я должен рассмотреть некоторые другие решения?
  2. Какими будут шаги для достижения указанных соединений?

1 Ответ

2 голосов
/ 16 февраля 2020

Я смотрю на нечто подобное и пришел к тому же выводу (1), поскольку в R2DB C нет поддержки отношений. Чтобы перенести отношение «один ко многим», я сначала создал коллекцию, содержащую «многие» сущности, в @Transient в «единой» сущности. Сохранение «единого» объекта выполняется с помощью следующих шагов в реактивной последовательности:

  1. Сохранение «многих» объектов. Это необходимо для того, чтобы можно было обновить их в «едином» объекте, чтобы «многим» объектам были назначены идентификаторы.
  2. Сохраните «один» объект.
  3. Сохраните отношения. Я могу сделать это на этом этапе, так как теперь у меня есть идентификаторы всех вовлеченных лиц. Для отношений я ввел вспомогательную сущность, что-то вроде OneManyRelation и соответствующий репозиторий.

В коде это выглядит так:

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);
            });
    });
}

Мой вывод на данный момент в том, что если вы не уверены в том, что от переключения на R2DB C можно добиться больших выгод, я бы согласился на использование Spring Data JPA и выполнение вызовов в репозитории в отдельном потоке с помощью subscribeOn. Удачи и удачного кодирования!

...