SpringBoot POST API多表插入:避免Skill表重复数据的实现方案
解决多对多关联下Skill重复插入问题的方案
核心逻辑
问题出在Cascade.ALL会无条件级联持久化关联的Skill实体,哪怕Skill已存在。解决方案是先校验Skill是否存在,复用已有实体,仅新增不存在的Skill,再完成用户、技能、评分的关联插入。
1. 调整实体级联配置
- 移除
UserDetails中skills集合上的Cascade.ALL注解,改用Cascade.PERSIST(仅持久化全新的Skill实体),或者直接不设置级联,完全由业务层控制Skill的持久化。 - 给
Skill实体的唯一标识字段(比如skillName)添加数据库唯一约束:@Column(name = "skill_name", unique = true, nullable = false) private String skillName;
2. 业务层实现Skill校验复用
在处理POST请求的Service方法中,对每个传入的Skill执行校验:
// 假设SkillRepository提供按名称查询的方法 Optional<Skill> existingSkill = skillRepository.findBySkillName(skill.getSkillName()); if (existingSkill.isPresent()) { // 使用数据库中已存在的Skill实体 skill = existingSkill.get(); } else { // 保存新的Skill到数据库 skill = skillRepository.save(skill); }
3. 完成三方关联插入
- 先处理所有Skill,得到最终的技能列表(包含已有和新增的),关联到
UserDetails。 - 创建
SkillRatings实体,绑定对应的UserDetails、处理后的Skill以及评分值。 - 最后保存
UserDetails和SkillRatings,确保操作在同一个事务中执行(添加@Transactional注解)。
完整Service代码示例
@Service @Transactional public class UserSkillService { @Autowired private UserDetailsRepository userDetailsRepo; @Autowired private SkillRepository skillRepo; @Autowired private SkillRatingsRepository skillRatingsRepo; public UserDetails createUserWithSkillsAndRatings(UserDetails userDetails) { // 预处理技能列表,复用已有技能 List<Skill> processedSkills = new ArrayList<>(); for (Skill skill : userDetails.getSkills()) { processedSkills.add(skillRepo.findBySkillName(skill.getSkillName()) .orElseGet(() -> skillRepo.save(skill))); } userDetails.setSkills(processedSkills); // 保存用户详情 UserDetails savedUser = userDetailsRepo.save(userDetails); // 绑定并保存技能评分 for (SkillRatings rating : savedUser.getSkillRatings()) { rating.setUserDetails(savedUser); // 确保评分关联的是已存在/刚保存的Skill Skill targetSkill = skillRepo.findBySkillName(rating.getSkill().getSkillName()).get(); rating.setSkill(targetSkill); skillRatingsRepo.save(rating); } return savedUser; } }
关键注意点
- 必须通过数据库唯一约束+业务层校验双重保证Skill不重复,避免并发场景下的竞态问题。
SkillRepository中需定义findBySkillName方法,或使用@Query自定义查询逻辑。- 整个操作必须在事务中执行,防止部分数据插入失败导致数据不一致。
内容的提问来源于stack exchange,提问作者Amit Sha
相关产品推荐
相关产品推荐

