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(...),(...)
现在是不可能的。
在 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(...),(...)
现在是不可能的。