Spring Boot未添加@NotNull却触发id非空校验的问题
问题:Spring Boot CRUD中触发id非空异常,未添加@NotNull注解却报错
我在使用Spring Boot结合H2数据库与Lombok开发CRUD功能时,遇到了如下错误:
java.lang.IllegalArgumentException: The given id must not be null
我疑惑的是,并没有在代码中添加@NotNull注解,却触发了这个非空校验要求,想了解原因。
Controller代码
package br.edu.unicesumar.crud.controller; import br.edu.unicesumar.crud.model.domain.Pessoa; import br.edu.unicesumar.crud.model.repository.PessoaRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/pessoa") public class PessoaController { @Autowired private PessoaRepository pessoaRepository; @GetMapping public List<Pessoa> all() { return pessoaRepository.findAll(); } @GetMapping("/{id}") public Pessoa getById(@PathVariable Long id) { return pessoaRepository.findById(id).orElse(null); } @PostMapping public Pessoa create(@RequestBody Pessoa nova) { return pessoaRepository.save(nova); } @DeleteMapping("/{id}") public void delete(@PathVariable Long id) { pessoaRepository.deleteById(id); } }
Entity代码
package br.edu.unicesumar.crud.model.domain; import jakarta.persistence.*; @Entity @Table(name = "ES_PESSOA") // para tabelas com nome diferente da entidade public class Pessoa { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String nome; @Column(name = "doc", length = 14) // se necessário, informar atribuições para a coluna private String documento; public Pessoa(Long id, String nome, String documento) { this.id = id; this.nome = nome; this.documento = documento; } public Pessoa() { } // getters e setters necessários para serializar e deserializar a classe para json public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getDocumento() { return documento; } public void setDocumento(String documento) { this.documento = documento; } }
Repository代码
package br.edu.unicesumar.crud.model.repository; import br.edu.unicesumar.crud.model.domain.Pessoa; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface PessoaRepository extends JpaRepository<Pessoa, Long> { }
原因分析
这个异常不是来自实体类的Bean Validation校验(比如@NotNull),而是Spring Data JPA自带的deleteById方法的内部校验逻辑。
Spring Data JPA的JpaRepository实现类中,deleteById方法会先做前置检查:如果传入的id参数为null,直接抛出IllegalArgumentException。这是框架为了避免无效的删除操作(删除不存在的/null记录)而设计的逻辑,和你有没有给实体类加@NotNull注解完全无关。
触发场景
最常见的触发情况是调用删除接口时,没有正确传递id参数:
- 请求路径写成了
/pessoa/(末尾多了斜杠,导致路径变量id未被正确解析) - 或者请求时路径中根本没带id(比如直接请求
/pessoa) - 少数情况是路径中的id无法被解析为Long类型(比如传了非数字字符串,但这种情况一般会先报类型转换错误,而非id null的异常)
解决建议
- 明确路径变量必填:在delete接口的@PathVariable上显式声明
required = true(默认就是true,但显式声明更清晰),确保请求必须携带有效id:
@DeleteMapping("/{id}") public void delete(@PathVariable(required = true) Long id) { pessoaRepository.deleteById(id); }
- 主动校验并返回友好提示:在调用deleteById前先判断id是否为null,返回符合REST规范的错误响应:
@DeleteMapping("/{id}") public ResponseEntity<Void> delete(@PathVariable Long id) { if (id == null) { return ResponseEntity.badRequest().build(); } pessoaRepository.deleteById(id); return ResponseEntity.noContent().build(); }
- 改用实体删除逻辑:先通过id查询实体,存在再执行删除,避免直接传递null的风险:
@DeleteMapping("/{id}") public void delete(@PathVariable Long id) { pessoaRepository.findById(id).ifPresent(pessoaRepository::delete); }
内容的提问来源于stack exchange,提问作者Prova Henrique
相关产品推荐
相关产品推荐

