-
Notifications
You must be signed in to change notification settings - Fork 37.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for batch operations (R2DBC) #27229
base: main
Are you sure you want to change the base?
Add support for batch operations (R2DBC) #27229
Conversation
Batching through We could follow the idea of Other than that, please check out the contribution guide to learn how we accept contributions. |
Thanks for the response.
Do you mean that we should check the expanded parameters count in NamedParameterUtils.substituteNamedParameters() or NamedParameter.addPlaceholder()? |
Is there any plans to add batching? |
@mp911de, correct me if I'm wrong, but the SPI has two ways of batching, right? One that allows you to send a single command with multiple parameters (via parameter binding) & another that allows you to pass multiple commands and, although both are sent in a single roundtrip, the latter one is slower since the database will have to parse every single command, so if your command won't change, you should stick with the first approach. I'm asking because the implementation of this PR is probably the most optimized (since it uses the first approach), although less flexible. Isn't there a way to add both ways to the |
@gabfssilva your perception is correct. Parametrized batching parses the command once and sends a execute command to the database for each binding set. I think it would be possible to bridge the |
It works for me now. @Autowired
private io.r2dbc.spi.ConnectionFactory connectionFactory;
@Transactional
public Mono<Void> update(List<User> users) {
String sql = "update user u set u.address=? where s.id=?";
return DatabaseClient.create(connectionFactory).sql(sql).filter(statement -> {
for (User u : users) {
statement.bind(0, u.getAddress()).bind(1, s.getId()).add();
}
return statement;
}).then();
} |
@mp911de I am happy helping the merge process but I could use a review on your side first. |
From the spec, we've learned that Considering batching with As a starting point, how about a databaseClient.sql("INSERT INTO legoset (id, name, manual) VALUES(:id, :name, :manual)")
.bind(params -> params.bind("name", name1).bind("manual", manual1))
.bind(params -> params.bind("name", name2).bind("manual", manual2))
.fetch(); The lambda parameter would be a simple interface carrying interface Params {
Params bind(String name, Object value);
Params bind(int index, Object value);
Params bindNull(String name, Class<?> type);
Params bindNull(int index, Class<?> type);
} |
@MarkMarkyMarkus would you have some cycle to amend your PR with the review of Mark? If not, that's cool we can take over when time permits. |
Yes, I will take a look. |
063786f
to
9bf751a
Compare
Note that we intentionally designed our new |
Hope there is a bind method to accept a list/array as params directly to avoid bind object one by one. .bind(
List.of(
Tuple.of(param1, param2, param3...),
Tuple.of(param1, param2, param3...),
...
)
) |
Add support for batch operations to the DefaultDatabaseClient:
Closes #259
Demo app: springR2dbcBatchExample.tar.gz