我的多条件查询
背景:2个表,是一对多的关系,一个实时视频帧可以出现多个检测结果
要求,可以根据,ids,起始时间,识别出的鸟的种类,来进行删除。
出现的问题,
一致性没有实现:
1.比如起始时间符合,但没判断type是否符合就进行了删除
原因:2个字段在不同的表,判断出问题
2.识别结果表中有剩余识别结果,但视频帧中仍然进行了删除
原因;是一对多关系,必须要
筛选出真正需要删除的 DetectionResult ID (即没有被其他 BirdAndconfidence 关联的)
api接口:
封装Bo:
public class DeleteCondition {private List<Integer> ids; // 根据 ID 列表删除@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)private LocalDate startDate; // 删除起始日期@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)private LocalDate endDate; // 删除结束日期 (如果只删除一天,则 startDate 和 endDate 相同)private List<String> birdTypes; // 根据鸟的类型列表删除}
controller层:
@DeleteMapping("/deleteBirds") public ResponseEntity<?> deleteBirds(@RequestBody DeleteCondition condition) {log.info("删除鸟类检测结果,参数:condition={}", condition);try {boolean isSuccess = birdSelectService.deleteBirdsByCondition(condition);if (isSuccess) {log.info("根据条件 {} 删除鸟类检测结果成功", condition);return ResponseEntity.ok("删除成功");} else {log.info("没有找到符合条件 {} 的鸟类检测结果,无需删除", condition);return ResponseEntity.ok("没有找到符合条件的鸟类检测结果,无需删除");}} catch (IllegalArgumentException e) {log.error("参数校验失败", e);return ResponseEntity.badRequest().body(e.getMessage()); // 400 Bad Request} catch (Exception e) {log.error("删除鸟类检测结果失败", e);return ResponseEntity.internalServerError().body("删除失败,请稍后重试"); // 500 Internal Server Error} }
service层:
// 1. 参数校验 validateDeleteCondition(condition);// 2. 构建 BirdAndconfidence 的 QueryWrapper QueryWrapper<BirdAndconfidence> birdQueryWrapper = new QueryWrapper<>();if (!CollectionUtils.isEmpty(condition.getIds())) {birdQueryWrapper.in("detection_results_id", condition.getIds()); // 根据 detection_results_id 删除 }
构建查询条件1:先 取出condition.getIds(),让删除结果要满足输入的ids
if (condition.getStartDate() != null) {// 根据日期范围查询 DetectionResultQueryWrapper<DetectionResult> detectionResultQueryWrapper = new QueryWrapper<>();if (condition.getEndDate() != null) {detectionResultQueryWrapper.ge("creat_time", condition.getStartDate().atStartOfDay()); // 大于等于起始日期detectionResultQueryWrapper.le("creat_time", condition.getEndDate().atTime(23, 59, 59)); // 小于等于结束日期} else {detectionResultQueryWrapper.eq("creat_time", condition.getStartDate().atStartOfDay()); // 等于指定日期}List<DetectionResult> detectionResults = detectionResultMapper.selectList(detectionResultQueryWrapper);if (!CollectionUtils.isEmpty(detectionResults)) {List<Integer> detectionResultIds = detectionResults.stream().map(DetectionResult::getId).collect(Collectors.toList());birdQueryWrapper.in("detection_results_id", detectionResultIds);} else {log.info("在指定日期范围内没有找到任何鸟类检测结果");return false; // 没有找到任何鸟类检测结果} }
构建查询条件2:查询出满足输入日期需求的ids,然后继续构建进来
if (!CollectionUtils.isEmpty(condition.getBirdTypes())) {birdQueryWrapper.in("bird_type", condition.getBirdTypes()); // 根据鸟的类型删除 }// 3. 查询需要删除的 BirdAndconfidence 记录 List<BirdAndconfidence> birdAndConfidenceList = birdAndconfidenceMapper.selectList(birdQueryWrapper);
构建查询条件3: 查询出满足输入种类需求的ids,然后继续构建进来
int deletedCount = birdAndconfidenceMapper.delete(birdQueryWrapper); log.info("成功逻辑删除 {} 条 BirdAndconfidence 记录", deletedCount);执行删除 BirdAndconfidence 操作
// 5. 找出所有需要删除的 DetectionResult ID List<Integer> detectionResultIdsToDelete = birdAndConfidenceList.stream().map(BirdAndconfidence::getDetectionResultsId).distinct().collect(Collectors.toList());// 6. 筛选出真正需要删除的 DetectionResult ID (即没有被其他 BirdAndconfidence 关联的) List<Integer> trulyDetectionResultIdsToDelete = detectionResultIdsToDelete.stream().filter(detectionResultId -> {QueryWrapper<BirdAndconfidence> countQueryWrapper = new QueryWrapper<>();countQueryWrapper.eq("detection_results_id", detectionResultId);int count = Math.toIntExact(birdAndconfidenceMapper.selectCount(countQueryWrapper));return count == 0; // 如果没有 BirdAndconfidence 引用这个 DetectionResult,则删除 }).collect(Collectors.toList());
// 7. 删除 DetectionResult 记录 (只删除没有被其他 BirdAndconfidence 关联的 DetectionResult 记录) if (!CollectionUtils.isEmpty(trulyDetectionResultIdsToDelete)) {int detectionResultDeletedCount = detectionResultMapper.deleteBatchIds(trulyDetectionResultIdsToDelete);log.info("成功逻辑删除 {} 条 DetectionResult 记录", detectionResultDeletedCount); }
先找出所有要删除的id,只有在检测结果表中的detection_results_id为0了,才删除对应的视频帧