Spring 数据 R2DBC,一次 sql 查询中的 saveAll()

Spring data R2DBC, saveAll() in one sql query

在 ReactiveCrudRepository 中我们有 saveAll 方法

<S extends T> reactor.core.publisher.Flux<S> saveAll(org.reactivestreams.Publisher<S> entityStream)
<S extends T> reactor.core.publisher.Flux<S> saveAll(Iterable<S> entities)

当我们保存包含N个元素的集合时,N个查询不是一个。例如,如果我们保存包含 2 个元素的集合,我们会得到 2 个查询,例如:

INSERT INTO test(id, value) VALUES (111, "value1");
INSERT INTO test(id, value) VALUES (222, "value2");

有没有办法在一个 SQL 查询中做到这一点?

INSERT INTO test(id, value) VALUES  (111, "value1"), (222, "value2");

可能需要映射到 Mono,但在这种情况下这对我来说没问题。

很遗憾,我认为目前不支持此功能。 查看spring-data-relational库,Insert语句接受一个值列表,但是每个值对应一列,无法添加不同的行。

如果你深入了解这个库,InsertBuilder 接口声明了这样的方法:

         /**
         * Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
         * a {@link Expression values} multiple times.
         *
         * @param values the values.
         * @return {@code this} builder.
         * @see Column
         */
        @Override
        InsertValuesWithBuild values(Expression... values);

并且实现将这些值存储到表达式列表中 (class DefaultInsertBuilder):

/**
 * Default {@link InsertBuilder} implementation.
 *
 * @author Mark Paluch
 * @since 1.1
 */
class DefaultInsertBuilder
        implements InsertBuilder, InsertBuilder.InsertIntoColumnsAndValuesWithBuild, InsertBuilder.InsertValuesWithBuild {

    private @Nullable Table into;
    private List<Column> columns = new ArrayList<>();
    private List<Expression> values = new ArrayList<>();

[...]

然后,呈现器 class(将语句转换为 SQL 字符串)将这些值添加到 VALUES(...) 中,每个值用逗号分隔 (class InsertStatementVisitor):

        if (segment instanceof Insert) {

            builder.append("INSERT");

            builder.append(" INTO ").append(into);

            if (columns.length() != 0) {
                builder.append(" (").append(columns).append(")");
            }

            builder.append(" VALUES (").append(values).append(")");

            return Delegation.leave();
        }

ValuesVisitor这里填写的值 class:

            if (first) {
                first = false;
            } else {
                builder.append(", ");
            }

            builder.append(this.current.getRenderedPart());

所以 spring-data-relational 的代码显示 SQL 像 VALUES(...),(...) 现在是不可能的。