在 Spring Boot 和 JPA 中保存具有非 null 外键的实体时出现 NullPointerException

NullPointerException when saving entity with non-null foreign key in Spring Boot and JPA

提问人:Eveprogram11 提问时间:5/12/2023 更新时间:5/12/2023 访问量:102

问:

我在Spring Boot应用程序中遇到了一个问题,在尝试使用JPA保存具有非null外键的实体时,我遇到了NullPointerException。我有一个 HistoriaClinica 实体,它与 Paciente 实体具有多对一关系。外键列 paciente_id 在数据库中不可为空。

但是,当我尝试使用有效的 pacienteId 保存新的 HistoriaClinica 实体时,我收到一个 NullPointerException,其中包含错误消息:“给定的 id 不得为 null”。我已经检查并确认 pacienteId 不为 null 并且存在于数据库中。

我已经查看了我的代码,并验证了 Paciente 和 HistoriaClinica 之间关系的映射和注释是否设置正确。我还检查了数据库配置,并确保存在必要的表和列。

我正在使用 Spring Boot 3.0.5 和 JPA 作为我的持久层。我在下面包含了相关的代码片段:

@Entity
@Table(name = "historias_clinicas")
@Getter
@Setter
public class HistoriaClinica {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "fecha_creacion", nullable = false)
    @JsonFormat(pattern = "dd-MM-yyyy")
    private Date fechaCreacion;

    private String enfermedad;

    private String descripcion;

    private String medicacion;
    
    private String droga;
    
    private String dósis;
    
    private Double peso;
    
    private Double altura;

    @Column(nullable = false)
    private String indicaciones;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "paciente_id", nullable = false)
    private Paciente paciente;

    @OneToMany(mappedBy = "historiaClinica", cascade = CascadeType.ALL)
    private List<ArchivoHistoriaClinica> archivosHistoriaClinica;

    @OneToMany(mappedBy = "historiaClinica", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Actualizacion> actualizaciones = new ArrayList<>();

    @OneToMany(mappedBy = "historiaClinica", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ArchivoHistoriaClinica> archivos = new ArrayList<>();
//respective constructors
@Getter @Setter
public class Paciente {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    
    private Long id;
    
    @Column(nullable = false)
    @NotNull
    private String nombre;
    
    @Column(nullable = false)
    @NotNull
    private String apellido;
    
    @Column(nullable = false, unique = true)
    @NotNull
    private String dni;
    
    @Column(name = "fecha_nacimiento")
    @NotNull
    private LocalDate fechaNacimiento;
    
    private String direccion;
    
    private String telefono;
    
    private String email;
    
    @Column(nullable = false)
    private String role = "ROLE_PACIENTE"; // anotación de rol

    
    @OneToMany(mappedBy = "paciente", cascade = CascadeType.ALL)
    private List<HistoriaClinica> historiasClinicas;

    public Paciente() {
    }

我调用的 HistoriaClinicaService 方法:

 public HistoriaClinica save(HistoriaClinicaDTO hcDTO, Long idPaciente) {
        Paciente paciente = pacienteRepository.findById(idPaciente)
                .orElseThrow(() -> new EntityNotFoundException("Paciente no encontrado con id " + idPaciente));

        HistoriaClinica hc = historiaClinicaMapper.toEntity(hcDTO);
        hc.setPaciente(paciente);

        List<Actualizacion> actualizaciones = hcDTO.getActualizaciones().stream()
                .map(actualizacionMapper::toEntity)
                .collect(Collectors.toList());
        hc.setActualizaciones(actualizaciones);

        List<ArchivoHistoriaClinica> archivos = hcDTO.getArchivos().stream()
                .map(archivoHistoriaClinicaMapper::toEntity)
                .collect(Collectors.toList());
        hc.setArchivos(archivos);
        actualizaciones.forEach(actualizacion -> actualizacion.setHistoriaClinica(hc));
        archivos.forEach(archivo -> archivo.setHistoriaClinica(hc));

        entityManager.persist(hc);
        return hc;
    }

和端点:

@PostMapping("/nuevas/{idPaciente}")
public ResponseEntity<HistoriaClinicaDTO> createHistoriaClinica(@RequestBody HistoriaClinicaDTO historiaClinicaDTO, @PathVariable("idPaciente") Long pacienteId) {
    // Verificar si el paciente existe
    Optional<Paciente> pacienteOptional = pacienteService.buscarPorId(pacienteId);
    if (!pacienteOptional.isPresent()) {
        throw new RuntimeException("No se encontró un paciente con el ID proporcionado.");
    }

    HistoriaClinica nuevaHistoriaClinica = historiaClinicaService.save(historiaClinicaDTO, pacienteId);

    HistoriaClinicaDTO newHistoriaClinicaDTO = historiaClinicaMapper.toDto(nuevaHistoriaClinica);

    return ResponseEntity.ok(newHistoriaClinicaDTO);
}

我尝试调试代码并检查每个步骤的值,但我无法确定 NullPointerException 的根本原因。我将不胜感激有关如何解决和解决此问题的任何见解或建议。

提前感谢您的帮助!

这是我到目前为止检查的内容:

  • “Paciente”实体有一个生成的“id”字段,该字段在保存新实例时自动分配。
  • “HistoriaClinica”实体与“Paciente”具有多对一关系,并且使用“paciente_id”外键正确定义关联。
  • 从存储库中检索“Paciente”时,会成功找到并返回它。
  • 在“HistoriaClinica”实体中设置“Paciente”对象之前,我已经验证了该对象是否具有有效的 ID。
  • 我已经检查了数据库,并且存在具有有效 ID 的关联“Paciente”记录。
  • 尽管进行了这些检查,但在尝试保留“HistoriaClinica”实体时,我仍然遇到“NullPointerException”,并显示“pacienteId不能为null”的消息。
java spring-boot nullpointerexception java-17

评论

1赞 Jim Garrison 5/12/2023
编辑您的帖子并包含完整的堆栈跟踪(格式化为代码)。在代码中查找导致异常的语句,并在代码清单中明确指示该语句。

答: 暂无答案