数据库重复值处理:存在时添加递增计数器的实现问题
解决方案
问题根源
你当前的代码只统计完全匹配原标题的记录数量,导致第一次生成「bar1」后,后续再尝试添加「bar」时,findByTitle("bar")返回的结果数还是1,所以会重复生成「bar1」,无法递增到「bar2」「bar3」。
修复思路
需要统计所有以原标题开头的记录(包括原标题本身和带数字后缀的),提取其中最大的计数器值,再生成新的递增标题:
- 查询所有标题以原标题开头的记录
- 解析这些标题的后缀数字,找出最大的计数器
- 根据最大计数器生成新标题:原标题不存在则直接用;存在则用「原标题 + 最大计数器+1」
代码实现
假设你的实体类是Quote,先在Repository中添加查询方法:
// Spring Data JPA 仓库接口 public interface NewQuoteRepository extends JpaRepository<Quote, Long> { List<Quote> findByTitleStartingWith(String prefix); }
然后修改业务逻辑代码:
String originalTitle = data.getTitle(); List<Quote> existingQuotes = newQuoteRepository.findByTitleStartingWith(originalTitle); int maxCounter = 0; boolean originalTitleExists = false; for (Quote quote : existingQuotes) { String title = quote.getTitle(); if (title.equals(originalTitle)) { originalTitleExists = true; continue; } // 提取后缀部分并尝试转为数字 String suffixPart = title.substring(originalTitle.length()).trim(); try { int counter = Integer.parseInt(suffixPart); if (counter > maxCounter) { maxCounter = counter; } } catch (NumberFormatException e) { // 后缀不是有效数字,跳过该记录 continue; } } // 生成最终标题 if (originalTitleExists) { data.setTitle(originalTitle + " " + (maxCounter + 1)); } // 如果原标题不存在,直接保留原标题即可
并发场景注意事项
如果有多个请求同时添加同标题的记录,可能会出现重复生成相同后缀的情况,你可以通过以下方式避免:
- 给
title字段添加唯一约束,当插入重复标题时捕获SQL异常,重新查询计数器后再次尝试插入 - 使用悲观锁:在查询时锁定相关记录,比如修改Repository方法为:
确保同一时间只有一个线程能处理同标题的生成逻辑@Lock(LockModeType.PESSIMISTIC_WRITE) List<Quote> findByTitleStartingWith(String prefix);
内容的提问来源于stack exchange,提问作者xRay
相关产品推荐
相关产品推荐

