使用以下方式使用 jOOQ 进行更新。
for (Balance balance : balances) {
dslContext.update(BALANCE)
.set(BALANCE.AMOUNT, balance.getAmount())
.where(BALANCE.ID.eq(balance.getId))
.execute();
}
Run Code Online (Sandbox Code Playgroud)
这将遍历所有余额并插入每个余额。我知道这可以使用 UpdatableRecord 来完成。但我想避免从数据库中获取余额。Balance 是包含超过 8 个字段的表,但我只对更新一个字段感兴趣。如果没有 UpdatableRecord,还有其他方法可以做到这一点吗?
Your code is fine but you could use the batch updates like this:
List<UpdateConditionStep<BalanceRecord> updates = new ArrayList<>();
for (Balance balance : balances) {
updates.add(dslContext.update(BALANCE)
.set(BALANCE.AMOUNT, balance.getAmount())
.where(BALANCE.ID.eq(balance.getId)));
}
dslContext.batch(updates).execute();
Run Code Online (Sandbox Code Playgroud)
Documentation: https://www.jooq.org/doc/3.14/manual-single-page/#batch-execution
Just a hint: Be careful of lost updates if you update a balance without locking.
UpdatableRecordUpdatableRecord如果您想要方便,您仍然可以使用DSLContext.batchUpdate(),而无需先从数据库中获取所有记录。假设您正在使用代码生成器并且正在生成记录,您将拥有BalanceRecord:
ctx.batchUpdate(balances
.stream()
.map(b -> {
var r = new BalanceRecord();
r.setAmount(b.getAmount());
r.setId(b.getId());
r.changed(BALANCE.ID, false); // Prevent setting the ID to itself
return r;
})
.collect(toList()))
.execute();
Run Code Online (Sandbox Code Playgroud)
这将为您在幕后创建一个批处理语句。
BatchedConnection从 jOOQ 3.14 开始,您可以使用 a 透明地批处理所有逻辑BatchedConnection,这是一个特殊的 JDBC 连接代理,它延迟所有 JDBC 语句(jOOQ 创建或未创建)的执行,缓冲它们直到需要执行:
dslContext.batched(c -> {
for (Balance balance : balances) {
c.dsl().update(BALANCE)
.set(BALANCE.AMOUNT, balance.getAmount())
.where(BALANCE.ID.eq(balance.getId))
.execute(); // This doesn't execute the query yet
}
} // Now, the buffered queries are being batch-executed
Run Code Online (Sandbox Code Playgroud)
根据您的评论,似乎希望将其作为单个批量语句运行,而不是在单个批处理语句中批处理多个语句(单次往返)。
我不相信这是正确的方法 - 语句可能会变得很大并且不一定比批处理快,但是当然,您可以使用表达式来做到这一点CASE
ctx.update(BALANCE)
.set(BALANCE.AMOUNT,
case_(BALANCE.ID).mapValues(
balances.stream().collect(toMap(balance::getId, balance::getValue))
)
)
.where(BALANCE.ID.in(balances.stream().map(balance::getId).collect(toList())))
.execute();
Run Code Online (Sandbox Code Playgroud)
这将产生类似的东西:
UPDATE balance
SET amount =
CASE id
WHEN 1 THEN 2.50
WHEN 2 THEN 3.50
WHEN 13 THEN 8.30
END
WHERE id IN (1, 2, 13)
Run Code Online (Sandbox Code Playgroud)
根据您使用的方言,这可能会更好地完成MERGE:
MERGE INTO balance
USING (
VALUES (1, 2.50), (2, 3.50), (13, 8.30)
) AS s (i, b)
ON balance.id = s.i
AND balance.balance = s.b
WHEN MATCHED THEN UPDATE SET balance = b
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2371 次 |
| 最近记录: |