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

Spring Boot:同时保存两个实体时出现NullPointerException求助

空指针异常排查:Spring Boot添加带Sprint列表的Projet实体失败

问题场景

开发Spring Boot应用时,尝试添加包含Sprint列表的Projet实体,调用添加接口触发NullPointerException,报错指向ProjetService类的projetRepository.save(projet)代码行。

相关代码

Projet实体类

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Entity
@Getter
@Setter
public class Projet {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String title;
    private String description;
    @ManyToMany(mappedBy = "projets")
    private List<User> users;
    @OneToMany(mappedBy = "projet")
    @JsonIgnore
    private List<Sprint> sprints;
}

Sprint实体类

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.Date;

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Sprint {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String description;
    @Temporal(TemporalType.DATE)
    private Date startDate;
    @ManyToOne
    @JsonIgnore
    private Projet projet;
}

ProjetRepository

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import tn.esprit.spring.entities.Projet;

@Repository
public interface ProjetRepository extends JpaRepository<Projet, Integer> {
}

ProjetService实现类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tn.esprit.spring.entities.Projet;
import tn.esprit.spring.entities.Sprint;
import tn.esprit.spring.repositories.ProjetRepository;

import java.util.List;

@Service
public class ProjetService implements IProjetService{
    @Autowired
    ProjetRepository projetRepository;
    @Override
    public Projet addProject(Projet projet) {
        List<Sprint> sprints = projet.getSprints();
        for ( Sprint sprint: sprints) {
            sprint.setProjet(projet);
        }
        return projetRepository.save(projet);
    }
}

ProjetController控制器

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tn.esprit.spring.entities.Projet;
import tn.esprit.spring.services.IProjetService;

@RequiredArgsConstructor
@RequestMapping("/projet")
@RestController
public class ProjetController {
    @Autowired
    IProjetService projetService;
    @PostMapping("/addProjet")
    public Projet addProject (@RequestBody Projet project){
        return projetService.addProject(project);
    }
}

请求详情

POST请求地址:http://localhost:8085/Exam/projet/addProjet
请求体:

{
    "title": "MAP",
    "description": "Gestion de Mandats, Assignations et Projets",
    "sprints": [
        {
            "description": "Sprint Projets",
            "startDate": "2023-05-27"
        }
    ]
}

错误信息

  • Postman返回500错误:
{
    "timestamp": "2023-05-17T13:45:51.279+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/Exam/projet/addProjet"
}
  • IDE控制台报错:
java.lang.NullPointerException: null
    at tn.esprit.spring.services.ProjetService.addProject(ProjetService.java:21) ~[classes/:na]
    at tn.esprit.spring.controllers.ProjetController.addProject(ProjetController.java:20) ~[classes/:na]
2023-05-17 14:56:42.938 ERROR 8448 --- [nio-8085-exec-4] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/Exam] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

原因分析

报错行对应ProjetService中的这段代码:

List<Sprint> sprints = projet.getSprints();
for ( Sprint sprint: sprints) {
    sprint.setProjet(projet);
}

空指针的核心原因是:Projet实体的sprints字段加了@JsonIgnore注解,导致Jackson无法将请求体中的sprints数组反序列化到Projet对象中,projet.getSprints()返回null,直接遍历null列表触发异常。

解决方法

1. 移除Projet实体中sprints的@JsonIgnore注解

让Jackson能正确映射请求体中的sprints数据:

@OneToMany(mappedBy = "projet")
// 移除@JsonIgnore
private List<Sprint> sprints;

注:若担心查询Projet时出现循环引用,可保留Sprint实体中projet字段的@JsonIgnore,避免序列化时嵌套返回关联对象。

2. 添加空值判断(兼容方案)

如果需要保留@JsonIgnore(比如不想在查询接口返回sprints),需在Service层先判断列表是否为null:

@Override
public Projet addProject(Projet projet) {
    List<Sprint> sprints = projet.getSprints();
    // 先判断列表非空再遍历
    if (sprints != null && !sprints.isEmpty()) {
        for ( Sprint sprint: sprints) {
            sprint.setProjet(projet);
        }
    }
    return projetRepository.save(projet);
}

注意:此方案下请求体中的sprints数据不会被映射到Projet对象,仅用于避免空指针,若需要接收前端传入的sprints数据,优先选择第一种方法。

3. 补充级联保存配置(可选)

为确保Sprint能随Projet自动保存,可在Projet的sprints字段添加级联配置:

@OneToMany(mappedBy = "projet", cascade = CascadeType.ALL)
private List<Sprint> sprints;

这样调用projetRepository.save(projet)时,关联的Sprint会自动插入数据库。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:40:35