跳到主要内容

插入冲突

冲突处理用于决定 INSERT 遇到主键或唯一约束冲突时应当报错、忽略还是更新,常见于任务重放、数据同步、重复导入和“存在则更新”场景。判断和写入由 PostgreSQL 在一条语句中完成,不需要先查询再决定 INSERT 或 UPDATE。

处理方式

策略PostgreSQL 语句结果
IntoINSERT INTO ... VALUES (...)冲突时由数据库报错
IgnoreINSERT ... ON CONFLICT DO NOTHING发生可处理的唯一冲突时不写入
UpdateINSERT ... ON CONFLICT (主键列) DO UPDATE SET ...主键冲突时更新非主键列

Ignore 不指定冲突目标;Update 使用实体映射中的主键列作为冲突目标。

如何使用

假设 UserInfo 映射到下表,id 配置为实体主键。表中已经有一条 Alice:

CREATE TABLE user_info (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(64),
age INTEGER
);
INSERT INTO user_info (id, name, age) VALUES (1001, 'Alice', 18);

再次提交相同 ID,但将名字改为 Bob:

UserInfo user = new UserInfo();
user.setId(1001);
user.setName("Bob");
user.setAge(20);

int rows = lambda.insert(UserInfo.class)
.onDuplicateStrategy(DuplicateKeyStrategy.Update)
.applyEntity(user)
.executeSumResult();

使用 Update 后,1001 这条记录变为 Bob、20 岁。改为 Ignore 则保留 Alice;默认 Into 会报告主键重复。

将策略改为 Ignore 可跳过冲突行;省略配置或使用 Into 则执行普通 INSERT。需要指定其他唯一键、条件或更新表达式时,应使用 Mapper 或 JdbcTemplate 编写完整 ON CONFLICT。通用 API 说明见新增操作

注意事项

  • Update 必须配置实体主键,且至少提供一个可更新的非主键列。
  • 映射主键必须对应 PostgreSQL 可用于 ON CONFLICT 的有效唯一约束。
  • dbVisitor 不会自动推断其他业务唯一键,也不会自动选择条件更新规则。
  • Ignore 返回 0 表示该行未插入;Update 的返回值不能区分实际执行了插入还是更新。