Controller中Laboratorian与Patient ID返回null问题排查
问题:ModelMapper映射后关联实体ID返回null
我使用Java开发,Service层从数据库获取diagnosisTitle、givenDate等字段值,Report实体通过关联关系关联Laboratorian和Patient。调用findById能正常获取Report数据,但Controller返回结果中Laboratorian ID(labIdNo)和Patient ID(patientId)为null,怀疑是Model Mapping配置错误。
相关代码及返回结果
Service代码
public ReportResponse findReportById(Long id) { Optional<Report> report = reportRepository.findById(id); if(report.isPresent()){ return modelMapper.map(report.get(), ReportResponse.class); } return null; }
Controller代码
@GetMapping("/findById/{id}") public ResponseEntity<ReportResponse> findReportById(@PathVariable("id") Long id){ ReportResponse resultReport = reportService.findReportById(id); return ResponseEntity.ok(resultReport); }
Postman返回结果
{ "fileNo": 102, "diagnosisTitle": "Kriz", "diagnosis": "Açıklama", "givenDate": "2023-02-27T08:07:41.382+00:00", "imageName": null, "labIdNo": null, "patientId": null }
可能的原因及解决方法
1. 关联实体懒加载未触发
JPA默认对关联实体采用懒加载,调用findById获取Report时,关联的Laboratorian和Patient并未实际从数据库加载,导致ModelMapper映射时无法获取对应ID。
- 解决方式:
在Repository接口的findById方法上添加@EntityGraph注解,强制加载关联实体:@Repository public interface ReportRepository extends JpaRepository<Report, Long> { @EntityGraph(attributePaths = {"laboratorian", "patient"}) Optional<Report> findById(Long id); }
2. ModelMapper字段映射不匹配
若Report实体中关联对象的ID路径(如laboratorian.id)与ReportResponse中的字段名(labIdNo)不一致,ModelMapper无法自动完成映射。
- 解决方式:
配置ModelMapper的自定义映射规则,指定字段对应关系:@Bean public ModelMapper modelMapper() { ModelMapper modelMapper = new ModelMapper(); modelMapper.typeMap(Report.class, ReportResponse.class) // 处理Laboratorian ID映射,添加空判断避免空指针 .addMapping(report -> report.getLaboratorian() != null ? report.getLaboratorian().getId() : null, ReportResponse::setLabIdNo) // 处理Patient ID映射 .addMapping(report -> report.getPatient() != null ? report.getPatient().getId() : null, ReportResponse::setPatientId); return modelMapper; }
3. 实体关联关系配置错误
如果实际业务是一个Report对应一个Laboratorian和一个Patient,那么应该使用@ManyToOne而非@OneToMany关联,错误的关联类型会导致无法正确获取关联实体ID。
- 正确的关联配置示例:
注:如果业务确实是@Entity public class Report { // 其他字段... @ManyToOne(fetch = FetchType.LAZY) // 配合EntityGraph按需加载,或设为EAGER立即加载 @JoinColumn(name = "laboratorian_id") private Laboratorian laboratorian; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "patient_id") private Patient patient; // Getter和Setter方法 }@OneToMany(一个Report对应多个关联实体),那么ReportResponse中的labIdNo和patientId应该设计为集合类型(如List<Long>),而非单个ID字段。
内容的提问来源于stack exchange,提问作者gls
相关产品推荐
相关产品推荐

