Spring中保存Machine实体因ID为空报错,User却正常的原因咨询
问题分析与解决
问题描述
使用Java Spring开发应用时,定义了User和Machine两个实体,代码如下:
User实体代码
@Getter @Setter @Entity @Table public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @NotNull private Long id; // etc. }
Machine实体代码
@Getter @Setter @Entity @Table public class Machine { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @NotNull private Long id; @ManyToOne @JoinColumn(name = "created_by") @NotNull private User createdBy; }
保存新User时不传入ID可成功保存,但保存新Machine时不传入ID会触发验证失败,报错信息翻译为:
ConstraintViolationImpl{插值消息='不能为空', 属性路径=id, 根Bean类=class raf.edu.rs.nwpbackend.model.Machine, 消息模板='{javax.validation.constraints.NotNull.message}'}
传入ID或移除@NotNull注解则可成功保存,二者配置相同且保存方式一致,询问原因。
原因解析
@NotNull与IDENTITY生成策略的逻辑冲突:
当使用GenerationType.IDENTITY生成策略时,实体ID的值是由数据库在插入操作时自动生成的,插入前实体的ID字段值为null。但@NotNull注解会触发Bean Validation(JSR-380)的非空校验,这本身就和IDENTITY策略的运作逻辑矛盾。两个实体的验证触发差异:
User实体没有关联其他带@NotNull约束的字段,Spring Data JPA或Hibernate在保存时可能绕过了完整的Bean Validation流程,导致ID字段的@NotNull约束未被触发。Machine实体存在@ManyToOne关联的@NotNull字段createdBy,这个字段的校验触发了完整的Bean Validation,此时ID字段的@NotNull约束也被检查到,因值为null而触发报错。
解决办法
直接移除@Id字段上的@NotNull注解即可。因为IDENTITY策略下,数据库会保证ID非空且自增,无需通过Bean Validation提前校验。
内容的提问来源于stack exchange,提问作者Nikola Grujic
相关产品推荐
相关产品推荐

