Spring Boot中基于ClassId和CurriculumMapId实现记录复用或新建的问题
问题解决:ContentSaveUserEvent事件中复用已有Class_CurriculumMap记录的实现
需求说明
接收到ContentSaveUserEvent事件时,检查Class_CurriculumMap表中是否存在ClassId与CurriculumMapId匹配的记录:
- 存在则复用该记录(更新必要字段)
- 不存在则创建新记录
现有代码问题分析
- 查询返回类型不合理:当前查询返回
List<Class_CurriculumMap>,但ClassId+CurriculumMapId是复合主键,最多只会有一条匹配记录,用Optional<Class_CurriculumMap>更符合语义且简化逻辑。 - 原生查询语法错误:
CurriculumMapId='?2'中的单引号会导致参数被视为字符串字面量?2,无法正确替换传入的参数值,需去掉单引号。 - 复用逻辑缺失:已有记录时未对记录进行更新操作,而Spring Data JPA的
save()方法在实体主键存在时会自动执行更新,而非插入,这正是复用的核心逻辑。
解决方案及完整代码
1. 修正Repository查询方法
将返回类型改为Optional<Class_CurriculumMap>,并修复查询语句的单引号问题:
@Query(value = "select * from class_curriculummap where ClassId = ?1 And CurriculumMapId = ?2", nativeQuery = true) Optional<Class_CurriculumMap> findByClassIdAndCurriculumMapId(Long classId, String curriculumMapId);
2. 完善事件处理方法的复用逻辑
使用ifPresentOrElse简化分支判断,复用记录时更新必要字段后调用save()执行更新:
@EventHandler @Override public void on(ContentSaveUserEvent event) { Long classId = Long.valueOf(event.getClassId()); String curriculumMapId = event.getCurriculumMapId(); classesCurriculumMapRepository.findByClassIdAndCurriculumMapId(classId, curriculumMapId) .ifPresentOrElse( // 复用现有记录:更新修改时间、修改人等字段后保存(自动执行更新) existingRecord -> { existingRecord.setDateLastModified(new Date()); existingRecord.setUserLastModified(event.getUctx().getUserId()); existingRecord.setStatus(Status.Active.value); classesCurriculumMapRepository.save(existingRecord); }, // 不存在则创建新记录 () -> { Class_CurriculumMap newRecord = new Class_CurriculumMap(); newRecord.setId(new Class_CurriculumMapPK(classId, curriculumMapId)); newRecord.setDateLastModified(new Date()); newRecord.setUserLastModified(event.getUctx().getUserId()); newRecord.setStatus(Status.Active.value); classesCurriculumMapRepository.save(newRecord); } ); }
关键逻辑说明
- 复用核心:当记录存在时,修改实体的可变字段(如
dateLastModified、userLastModified),调用save()方法会触发Spring Data JPA的更新操作,而非插入新记录。 - Optional优化:用
ifPresentOrElse替代传统的isEmpty()判断,代码更简洁易读,避免空指针风险。
内容的提问来源于stack exchange,提问作者Mahrukh Saeed
相关产品推荐
相关产品推荐

