Spring Data REST自定义控制器HATEOAS列表查询异常问题
解决Spring Data REST自定义Controller列表请求抛出“PersistentEntity must not be null!”异常
这个问题我之前也碰到过,核心原因是你误用了PersistentEntityResourceAssembler的toResource方法——它是为单个实体设计的,直接传入列表集合的话,Spring无法识别集合类型对应的PersistentEntity元数据,自然就抛出空指针异常了。
问题根源
当处理单个实体请求时,PersistentEntityResourceAssembler会自动根据实体类(比如EmploymentType)找到对应的PersistentEntity(Spring Data REST用来描述实体元数据的类),从而生成符合HATEOAS规范的响应。但你传入List<EmploymentType>时,Assembler找不到集合类型对应的PersistentEntity,就会触发'PersistentEntity must not be null!'错误。
解决方案:逐个转换实体并包装为资源集合
你需要遍历列表中的每个实体,用Assembler逐个转换为PersistentEntityResource,再把这些资源包装成Resources集合(Spring HATEOAS提供的集合资源类型),同时添加必要的HATEOAS链接。
以下是修正后的Controller代码示例:
import org.springframework.hateoas.Resources; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.List; import java.util.stream.Collectors; @RestController public class EmploymentTypeController { private final EmploymentTypeRepository employmentTypeRepository; // 构造注入Repository public EmploymentTypeController(EmploymentTypeRepository employmentTypeRepository) { this.employmentTypeRepository = employmentTypeRepository; } @RequestMapping(value="/employmentType", method=RequestMethod.GET, produces="application/hal+json") public ResponseEntity<Resources<PersistentEntityResource>> getEmploymentTypes(PersistentEntityResourceAssembler assembler) { // 1. 获取实体列表 List<EmploymentType> employmentTypes = employmentTypeRepository.findAll(); // 2. 逐个转换实体为PersistentEntityResource List<PersistentEntityResource> resourceList = employmentTypes.stream() .map(assembler::toResource) .collect(Collectors.toList()); // 3. 包装为Resources集合,并添加自链接 Resources<PersistentEntityResource> resourceCollection = new Resources<>(resourceList); resourceCollection.add(WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(EmploymentTypeController.class).getEmploymentTypes(assembler)) .withSelfRel()); return ResponseEntity.ok(resourceCollection); } }
额外注意事项
- 确保你的实体类(
EmploymentType)和Repository(EmploymentTypeRepository)在Spring Data REST的扫描路径下,这样Spring才能正确生成PersistentEntity元数据。 - 如果需要支持分页查询,可以改用
PagedResourcesAssembler,它会自动处理分页链接的生成,用法类似但针对分页结果集。
内容的提问来源于stack exchange,提问作者Avinash Sagar
相关产品推荐
相关产品推荐

