如何在r2dbc中批量执行多次插入?

voi*_*ipp 9 spring r2dbc

我需要批量将多行插入到一个表中。在 DatabaseClient 中,我发现 insert() 语句和 using(Publisher objectToInsert) 方法有多个对象作为参数。但它是否会将它们批量插入?另一个可能的解决方案是connection.createBatch(),但它有一个缺点:我无法在那里传递我的实体对象,并且无法从实体生成sql查询。

那么,是否可以在r2dbc中创建批量插入?

Han*_*tsy 9

到目前为止还没有直接支持,但我发现可以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)));
        });
Run Code Online (Sandbox Code Playgroud)

对该方法进行了测试。

@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();
    }
Run Code Online (Sandbox Code Playgroud)

生成的 id 按预期打印在控制台中。

...
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

Run Code Online (Sandbox Code Playgroud)

  • 重要提示:为了确保插入确实发生,**需要**对**每个**返回的“Result”调用“getRowsUpdated()”或“map(...)”并包含它们结果形成反应链。仅仅执行“Flux.from(statement.execute()).then()”之类的操作是不够的。 (3认同)

Mir*_*tth 7

有两个问题:

是否将DatabaseClient.insert()它们批量插入?

不是一批。

是否可以在 r2dbc 中创建批量插入?(除了Connection.createBatch()

不,使用只是Connection.createBatch()目前Batch创建.

另请参阅问题: