Reputation: 43206
What is the proper way to do batch updates with JOOQ?
I have the following:
public void updateScores(Map<String, Integer> teamScores) {
writeContext().transaction(config -> {
DSLContext dslContext = DSL.using(config);
dslContext.batchUpdate(Maps.transformEntries(teamScores, (id, score) -> {
TeamScoresRecord record = new TeamScoresRecord();
record.setTeamId(id);
record.setScore(score);
return record;
}).values()).execute();
});
}
OR
public void updateScores(Map<String, Integer> teamScores) {
writeContext().transaction(config -> {
DSLContext dslContext = DSL.using(config);
dslContext.batchUpdate(
dslContext.selectFrom(TEAM_SCORES)
.where(TEAM_SCORES.TEAM_ID.in(teamScores.keySet()))
.forUpdate()
.fetch()
.stream()
.peek(record -> record.setScore(teamScores.get(record.getTeamId())))
.collect(Collectors.toList())
).execute();
});
}
Which of these is the recommended way to do batch updates?
Upvotes: 1
Views: 3613
Reputation: 221145
This question is obviously very subjective and not easy to answer. Here are a few observations:
UPDATE
statementSELECT
query, which might be quite expensive, depending on the size of the in-list). Without the FOR UPDATE
clause, however, the first approach might have a higher deadlocking risk.ID
values that have been deleted in the meantime. The second approach prevents that from happeningNow, I don't know MySQL well enough to know if a bulk update statement might be better here, i.e. a statement of the kind:
UPDATE team_scores
SET score = CASE id
WHEN :id1 THEN :score1
WHEN :id2 THEN :score2
WHEN :id3 THEN :score3
...
END
WHERE id IN (:id1, :id2, :id3, ...)
Perhaps you could benchmark this approach and compare it to batching (or combine it with batching, e.g. bulk update 10 rows and batch all these bulk updates)
Upvotes: 3