You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的异常)

解决建议

  1. 明确路径变量必填:在delete接口的@PathVariable上显式声明required = true(默认就是true,但显式声明更清晰),确保请求必须携带有效id:
@DeleteMapping("/{id}")
public void delete(@PathVariable(required = true) Long id) {
    pessoaRepository.deleteById(id);
}
  1. 主动校验并返回友好提示:在调用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();
}
  1. 改用实体删除逻辑:先通过id查询实体,存在再执行删除,避免直接传递null的风险:
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
    pessoaRepository.findById(id).ifPresent(pessoaRepository::delete);
}

内容的提问来源于stack exchange,提问作者Prova Henrique

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 23:17:37