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

Spring Data MongoDB 3.4.12:解决@DBRef列表添加对象时为空的问题

问题:MongoDB中无法向Curso对象的Student列表添加元素及@DBRef相关疑问

在Postman测试REST API时,尝试通过Spring Data MongoDB将Student对象添加到Curso的列表属性中,但发现该列表为null,无法添加值。同时疑问使用@DBRef注解时是否无法访问Student的持久化元素。

相关代码

@Document
public class Student {
    @Id
    private String id;
    @Getter @Setter
    private String primer_nombre;
    @Getter @Setter
    private String segundo_nombre;
    @Getter @Setter
    private String primer_apellido;
    @Getter @Setter
    private String segundo_apellido;
    @Getter @Setter
    private String numero_documento;
    @Getter @Setter
    private documentType tipo_documento;
    @Getter @Setter
    private int nota;
    @Getter @Setter
    private String estado;

    public void calificarEstudiante(){
        if(this.getNota() < 3){
            this.setEstado("reprobado");
        }else{
            this.setEstado("aprobado");
        }
    }
}

@Data
@Document
public class Curso {
   @Id
   @Getter @Setter
   private String id;
   @Getter @Setter
   private String nombre_curso;
   @Getter @Setter
   private String descripcion;
   @Getter @Setter
   private String maestro;
   @DBRef
   @Field("estudiantes")
   public List<Student> estudiantes;

   public void addStudentsInCourse(Student student){
      System.out.println("estudiantes = " + estudiantes); //students is null
      this.estudiantes.add(student);
   }
}

// Controller
@RestController
@RequestMapping("/endpoints")
public class QualificationsController {
   @PutMapping("/inscribir/{studentID}/in/{cursoID}")
   public Curso agregarEstudianteACurso(
        @PathVariable(value="studentID")
        String studentID,
        @PathVariable(value="cursoID")
        String cursoID)
   {
        Curso currentCurso = cursosServices.findById(cursoID);
        Student currentStudent = studentsServices.findById(studentID);
        currentCurso.addStudentsInCourse(currentStudent);
        return this.cursosServices.save(currentCurso);
   }
}

解决方案及说明

1. 解决列表为null的问题

Curso类中的estudiantes列表未初始化,从MongoDB查询时如果该字段不存在,会返回null,导致调用add()方法时抛出NullPointerException。有两种修复方式:

  • 方式一:声明字段时直接初始化
    修改Curso类的列表字段(建议改为private,利用@Data自动生成getter/setter,符合封装原则):
@DBRef
@Field("estudiantes")
private List<Student> estudiantes = new ArrayList<>();
  • 方式二:在add方法中做null判断
    如果不想提前初始化,可在添加元素前先检查并初始化:
public void addStudentsInCourse(Student student){
    if(this.estudiantes == null){
        this.estudiantes = new ArrayList<>();
    }
    this.estudiantes.add(student);
}

2. @DBRef注解的说明

使用@DBRef时可以正常访问Student对象的持久化元素,它的核心作用是存储关联文档的_id引用,而非嵌入整个Student文档:

  • 关联的Student必须已持久化到MongoDB中(即先调用studentsServices.save()保存Student,再关联到Curso),否则Spring Data MongoDB无法找到对应的引用文档。
  • 查询Curso时,Spring会自动根据@DBRef加载关联的Student对象(默认立即加载,可通过配置调整为懒加载)。
  • 持久化Curso时,Spring会自动将Student的_id作为引用存储到Curso的estudiantes字段中。

3. 增强接口健壮性

建议在控制器中添加空判断,避免因Curso或Student不存在导致的异常:

@PutMapping("/inscribir/{studentID}/in/{cursoID}")
public Curso agregarEstudianteACurso(
     @PathVariable(value="studentID") String studentID,
     @PathVariable(value="cursoID") String cursoID)
{
     Curso currentCurso = cursosServices.findById(cursoID);
     if(currentCurso == null){
         throw new RuntimeException("Curso no encontrado con ID: " + cursoID);
     }
     Student currentStudent = studentsServices.findById(studentID);
     if(currentStudent == null){
         throw new RuntimeException("Estudiante no encontrado con ID: " + studentID);
     }
     currentCurso.addStudentsInCourse(currentStudent);
     return this.cursosServices.save(currentCurso);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:17:55