【问题标题】:Spring data R2DBC, saveAll() in one sql query一个 sql 查询中的 Spring 数据 R2DBC、saveAll()
【发布时间】:2021-12-14 13:41:06
【问题描述】:

在 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 spring-boot spring-data spring-data-r2dbc r2dbc


    【解决方案1】:

    很遗憾,我认为目前不支持此功能。 查看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);
    

    实现将这些值存储到表达式列表中(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<>();
    
    [...]
    

    然后,渲染器类(将语句转换为 SQL 字符串)将这些值添加到 VALUES(...) 中,每个值用逗号分隔(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 类中填写此处的值:

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

    所以 spring-data-relational 的代码表明,现在不可能有​​像 VALUES(...),(...) 这样的 SQL。

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 1970-01-01
      • 2020-07-13
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      • 2021-09-22
      • 2021-03-07
      • 2020-03-11
      相关资源
      最近更新 更多