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

调用CrudRepository.save()报JPASystemException:需手动分配实体ID问题

问题:调用repository.save()保存MeasurementsFile失败,已设置ID仍报错

问题详情

尝试将MeasurementsFile对象保存至仓库时,repository.save(measurementsFile)完全无效。此前解析器返回空List<MeasurementRow>时代码可正常运行,现在却出现异常。测试时硬编码ID为0L,上传接口返回“could not upload...”提示,且程序在打印“inserted measurementRows”日志后停止,即使移除.setId()和.setMeasurementsMic1()操作,问题依然存在。

相关代码

控制器上传接口

@PostMapping("/upload")
public ResponseEntity<ResponseMessage> uploadMeasurements(@RequestParam("file") MultipartFile file) {
    String message = "";
    logger.info("POST: excel");
    if (ExcelHelper.hasExcelFormat(file)) {
        try {
            logger.info("file name: "+file.getOriginalFilename());
            fileService.saveMeasurementsFile(file,0L);
            message = "Uploaded the file successfully: " + file.getOriginalFilename();
            return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
        } catch (Exception e) {
            message = "Could not upload the file: " + file.getOriginalFilename() + "!";
            return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
        }
    }
    message = "Please upload an excel file!";
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseMessage(message));
}

文件服务的saveMeasurementsFile方法

public void saveMeasurementsFile(MultipartFile file, long id) {
    try {
        logger.info("reached before excelhelper is called, input stream:"+file.getInputStream()+" with name "+ file.getOriginalFilename() +" and contenttype: "+ file.getContentType());

        List<MeasurementRow> measurementRows = ExcelHelper.toMeasurementRows(file.getInputStream());
        logger.info(""+measurementRows.size()+" rows");
        MeasurementsFile measurementsFile = new MeasurementsFile();
        logger.info("created new MeasurementsFile");
        measurementsFile.setMeasurementsMic1(measurementRows);
        logger.info("inserted measurementRows");
        measurementsFile.setId(id);
        logger.info("set id: "+id);
        measurementRepository.save(measurementsFile);
        logger.info("saved MeasurementsFile");
    } catch (IOException e) {
        throw new RuntimeException("fail to store excel data!");
    }
}

MeasurementsFile实体类

@Entity
public class MeasurementsFile {
    @Id
    private Long id;
    @Column
    @OneToMany
    private List<MeasurementRow> measurementsMic1;
    @Column
    @OneToMany
    private List<MeasurementRow> measurementsMic2;//当配置有两个麦克风时,需上传第二个输入文件
    @Column
    private double height;
    @Column
    private int[] referenceSpeeds; //乘用车和重型车辆的参考速度
    @Column
    private boolean hasSecondaryMic;
    @Column
    private boolean hasBackingboard;
    //列ID及其默认值
    private int numberColumnID=0;
    private int dateColumnID=0;
    private int timeColumnID=0;
    private int vehicleColumnID=0;
    private int speedColumnID=0;
    private int airTempColumnID=0;
    private int roadTempColumnID=0;//(可选)
    private int windSpeedColumnID=0;//(可选)
    private int laMaxColumnID=0;
    private int laMaxArrayColumnID=0;//默认26个元素(可选)
}

(已省略自动生成的导入、Getter和Setter方法)

错误信息

打印异常栈信息得到:

org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): be.uantwerpen.ft.se.tutorial_backend.model.users.MeasurementsFile

明明已经调用.setId(id),为何仍报此错误?


解决方案

1. 修正关联字段的注解错误

@Column注解不能用于@OneToMany关联字段,这是错误用法,需直接移除关联字段上的@Column。同时补充级联配置,确保保存MeasurementsFile时能自动处理关联的MeasurementRow:

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<MeasurementRow> measurementsMic1;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<MeasurementRow> measurementsMic2;

2. 检查MeasurementRow的ID配置

报错的核心原因并非MeasurementsFile的ID,而是关联的MeasurementRow实体未正确设置ID生成策略。当保存MeasurementsFile时,JPA会级联保存关联的MeasurementRow列表,若MeasurementRow的ID需要手动分配但未设置,就会触发该错误。

如果MeasurementRow的ID是自增类型,需在其@Id字段添加生成策略注解:

@Entity
public class MeasurementRow {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 或根据数据库选择AUTO等策略
    private Long id;
    // 其他字段...
}

3. 验证MeasurementsFile的ID有效性

测试时使用的ID为0L,部分数据库不允许0作为合法主键值。可以尝试使用非0的合法ID,或者将MeasurementsFile的ID改为自动生成策略,无需手动设置:

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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:00:13