当向数据库插入数据时遇到重复记录,需要同时解决两个问题: 1. 如何优雅地提示用户数据重复 2. 如何避免重复提示给用户造成困扰
唯一性约束:首先确保数据库表设置了适当的唯一性约束(UNIQUE约束或主键)
ALTER TABLE your_table ADD CONSTRAINT unique_constraint_name UNIQUE (column1, column2);
public boolean insertIfNotExists(YourEntity entity) {
// 先查询是否存在
if (yourRepository.existsByUniqueFields(entity.getField1(), entity.getField2())) {
return false; // 已存在
}
yourRepository.save(entity);
return true;
}
public void insertWithGracefulDuplicateHandling(YourEntity entity) {
try {
yourRepository.save(entity);
} catch (DataIntegrityViolationException e) {
if (isDuplicateKeyError(e)) {
// 处理重复数据情况
handleDuplicateEntry(entity);
} else {
throw e; // 其他类型的数据完整性异常
}
}
}
private boolean isDuplicateKeyError(DataIntegrityViolationException e) {
// 根据具体数据库实现判断
return e.getRootCause() instanceof SQLIntegrityConstraintViolationException
|| e.getMessage().contains("Duplicate entry");
}
private void handleDuplicateEntry(YourEntity entity) {
// 实现优雅的提示逻辑
}
// 在调用API后处理响应
axios.post('/api/your-endpoint', data)
.then(response => {
// 成功处理
})
.catch(error => {
if (error.response.status === 409) { // 冲突状态码
showToast('该记录已存在,无需重复添加');
} else {
// 其他错误处理
}
});
@PostMapping("/your-endpoint")
public ResponseEntity<?> createEntity(@RequestBody YourEntity entity) {
try {
yourService.insertWithGracefulDuplicateHandling(entity);
return ResponseEntity.ok().build();
} catch (DuplicateEntryException e) {
return ResponseEntity.status(HttpStatus.CONFLICT)
.body(new ErrorResponse("记录已存在", "DUPLICATE_ENTRY"));
}
}
防抖(Debounce)技术:在前端实现,确保短时间内不会重复发送相同请求
const debouncedSave = _.debounce(saveData, 1000); // 使用lodash
乐观UI更新:先在前端显示结果,后台验证后再同步状态
// 先在前端添加
addToLocalList(newItem);
// 然后发送到后端
saveToBackend(newItem).catch(() => {
removeFromLocalList(newItem);
showError();
});
状态标记:为正在处理的数据项添加状态标记,防止重复操作
item.isSaving = true; // 禁用相关操作按钮
后端幂等性设计:确保重复请求不会产生副作用
根据业务场景选择合适的方案:
统一错误处理:
日志记录:
考虑使用UPSERT操作(INSERT ON DUPLICATE KEY UPDATE或MERGE)如果业务允许
通过以上方案组合,可以实现既优雅又用户友好的重复数据处理机制。