Как выполнить несколько вставок в пакетном режиме в r2dbc?

Мне нужно вставить несколько строк в одну таблицу одним пакетом. В DatabaseClient я нашел оператор insert () и использовал метод (Publisher objectToInsert), который имеет несколько объектов в качестве аргумента. Но вставит ли он их одной партией или нет? Другое возможное решение - connection.createBatch (), но у него есть недостаток: я не могу передать туда свой объект Entity и не могу сгенерировать sql-запрос из объекта.

Итак, можно ли создать пакетную вставку в r2dbc?


person voipp    schedule 22.06.2020    source источник


Ответы (2)


Есть два вопроса:

Будет ли DatabaseClient.insert() вставлять их в один пакет или нет?

Не партией.

Можно ли в r2dbc создать пакетную вставку? (кроме Connection.createBatch())

Нет, использование Connection.createBatch() - это только один из способов создания Batch сейчас.

См. Также вопросы: spring-data-r2dbc # 259

person Mirro Mutth    schedule 09.07.2020

До сих пор нет прямой поддержки, но я обнаружил, что можно использовать Connection, чтобы просто преодолеть этот барьер, проверьте эту проблему, spring-data-r2dbc # 259

statement имеет add, который нужно повторить для привязки параметров.

Полные коды моего решения можно найти здесь.

        return this.databaseClient.inConnectionMany(connection -> {

            var statement = connection.createStatement("INSERT INTO  posts (title, content) VALUES ($1, $2)")
                    .returnGeneratedValues("id");

            for (var p : data) {
                statement.bind(0, p.getTitle()).bind(1, p.getContent()).add();
            }

            return Flux.from(statement.execute()).flatMap(result -> result.map((row, rowMetadata) -> row.get("id", UUID.class)));
        });

Тест на этот метод.

@Test
    public void testSaveAll() {

        var data = Post.builder().title("test").content("content").build();
        var data1 = Post.builder().title("test1").content("content1").build();

        var result = posts.saveAll(List.of(data, data1)).log("[Generated result]")
                .doOnNext(id->log.info("generated id: {}", id));

        assertThat(result).isNotNull();
        result.as(StepVerifier::create)
                .expectNextCount(2)
                .verifyComplete();
    }

Сгенерированные идентификаторы печатаются в консоли должным образом.

...
2020-10-08 11:29:19,662 INFO [reactor-tcp-nio-2] reactor.util.Loggers$Slf4JLogger:274 onNext(a3105647-a4bc-4986-9ad4-1e6de901449f)
2020-10-08 11:29:19,664 INFO [reactor-tcp-nio-2] com.example.demo.PostRepositoryTest:31 generated id: a3105647-a4bc-4986-9ad4-1e6de901449f
//.....
2020-10-08 11:29:19,671 INFO [reactor-tcp-nio-2] reactor.util.Loggers$Slf4JLogger:274 onNext(a611d766-f983-4c8e-9dc9-fc78775911e5)
2020-10-08 11:29:19,671 INFO [reactor-tcp-nio-2] com.example.demo.PostRepositoryTest:31 generated id: a611d766-f983-4c8e-9dc9-fc78775911e5
//......

Process finished with exit code 0

person Hantsy    schedule 08.10.2020
comment
это решение использует пакетную обработку? - person jzqa; 19.04.2021
comment
Обратите внимание, что для некоторых драйверов (например, mariadb) требуются вопросительные знаки?,? вместо 1 $, 2 $ для работы привязки. - person Readren; 11.07.2021
comment
@Readren каждая БД имеет свой собственный заполнитель параметров в SQL, например. mssql использует префикс @, pg использует $ и т. д. - person Hantsy; 11.07.2021
comment
Важное примечание: чтобы убедиться, что вставки действительно происходят, требуется вызывать getRowsUpdated() или map(...) для каждого возвращенного Result и включать их результаты в реактивную цепочку. Недостаточно просто сделать что-то вроде Flux.from(statement.execute()).then(). - person Roman Puchkovskiy; 12.07.2021