postgresql - Jooq 中的原子批量插入/更新
问题描述
我有一个程序可以监视服务并保存它们的当前状态。我的程序会定期检查每个服务并将有关它们的信息存储在 postgres 中。大多数情况下,这涉及更新数据库中的现有行。但有时,也需要添加新服务。
我用一个看起来像这样的模式来存储它们:
CREATE TABLE services IF NOT EXISTS (
id SERIAL NOT NULL,
name TEXT NOT NULL,
status TEXT ,
PRIMARY KEY (id, name)
)
其中 ID 指定一台机器,名称指定该机器上的一项服务。POJO 非常简单:
public class Service {
int id;
String name;
String status;
}
例如,我的表可能只从一行开始:(22, "api", "active")
. 在预定的时间间隔内,我的程序确定现在有 2 个服务在一台机器上运行,并且当前服务的状态已经改变:
- (22,“api”,“错误”)
- (22,“消息”,“活动”)
我的方法如下所示:
Set<ServicesRecord> records = listServices
.stream()
.map(service -> {
ServicesRecord record = new ServicesRecord();
record.setId(service.id);
record.setName(service.name);
record.setStatus(service.status);
return record;
})
.collect(Collectors.toSet());
DSLContext dsl = DSL.using(this.configuration);
dsl.batchStore(records).execute();
}
但是,当我尝试运行它时,这给了我一个错误:
Caused by: org.jooq.exception.DataAccessException: SQL [insert into "foobar"."services" ("id", "name", "status", values (?, ?, ?)]; Batch entry 0 insert into "foobar"."services" ("id", "name", "status") values (1, 'testName', 'baz') was aborted: ERROR: duplicate key value violates unique constraint "services_pkey"
我可以看到batchStore
失败是因为它使用了UpdatableRecord
'sstore
方法,而后者又失败了,因为我正在创建一条新记录而不是从 jooq 获取一条记录。
我正在考虑这样的替代方法:
- 从数据库中获取所有记录。
- 对于每条匹配的记录
records
,我设置changed
为true
. - 然后我跑
batchStore
或者,我可以这样做吗?
- 从数据库中获取所有记录。
- 制作要插入和使用的记录列表
batchInsert
- 列出要更新的记录,修改它们的记录,并使用
batchStore
但这两者都有可能不是原子的。如果在执行第 2 步时数据库发生更改,我的使用batchStore
仍然会失败。我想要的是一种在单个操作中进行这种批量存储的方法,而不是先执行获取然后执行。有没有办法做到这一点?
解决方案
您正在寻找的是batchMerge()
,它将随 jOOQ 3.14 一起提供:https ://github.com/jOOQ/jOOQ/issues/10046
或者,您可以使用数据导入 API。然后,您可以将该onDuplicateKeyUpdate()
子句与适当的批量大小结合起来。
或者,您可以编写显式INSERT .. ON CONFLICT
语句并显式批处理它们。
推荐阅读
- c# - Regex Finding Name and Surname on the String for ID Card
- java - App crashes when trying to create a list of files from a directory
- wordpress - 通过 cron 调用的 wp_insert_post 重复帖子而不是更新它们
- c# - 网站上的图片突然出现403错误,无法加载
- python - Pandas grouped mode and missing values
- codenameone - 代号一个应用程序仅在 iOS 上被杀死(由 jetsam 原因每个进程限制),随机
- python-3.x - Unnest grab keywords/nextwords/beforewords function
- algorithm - Modified Booth 算法中添加到 LSB 的额外 0 有什么作用?
- ios - EXC_BAD_ACCESS with navigation bar title in SwiftUI
- mips - QtSpim Error "Attempt to execute non-instruction at 0x0040000c"