休眠抛出"NULL not allowed for column",因为使用 @MapsId 时 SQL 插入中缺少 JPA 一对一关系 FK



在我的一对一关系中,我得到:NULL not allowed for column "USER_ID"; SQL statement: insert into customer_order (id, enabled, orden_id) values (null, ?, ?).

它实际上是null的,因为它不存在于INSERT查询中。但是,当性能save(customerOrder)时,USER的值将填充customerOder实体中。

@Getter
@SuperBuilder
@MappedSuperclass
@NoArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public abstract class AbstractEntity {
@Id
@EqualsAndHashCode.Include
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Setter
@Default
@Column(columnDefinition = "BOOLEAN DEFAULT 'true'", nullable = false)
private Boolean enabled = Boolean.TRUE;
}
@Getter
@Setter
@Entity
@Table(name = "customer_order")
@SuperBuilder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
public class CustomerOrderEntity extends AbstractEntity {
@OneToOne(fetch = FetchType.LAZY)
@MapsId("id")
private UserEntity user;
//other values
}
@Data
@Entity
@Table(name = "user")
@SuperBuilder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
public class UserEntity extends AbstractEntity {
@NaturalId
@EqualsAndHashCode.Include
@Column(length = 28, unique = true, nullable = false)
private String uuid;
//other values
}

我希望customerOrder与填充的数据一起持久保存在数据库中。

使用@MapsId允许您将子表主键用作父表主键的外键。

如果启用hbm2ddl工具,您将看到customer_order表将不包含user_id列。

但是,由于您之前生成了数据库架构,并且您有一个带有专用user_id列的customer_order表,因此您需要删除@MapsId

@OneToOne(fetch = FetchType.LAZY)
private UserEntity user;

这样,user关联将使用"user_id外键"列。

您的代码完全按照您指定的方式工作。

如果您有共享密钥(使用 @MapsId),Hibernate 不会为外键使用单独的列。这就是插入查询不包含user_id列的原因。

最重要的是,CustomerOrderEntity 中的 id 一方面是自动生成的(如超类中所定义),另一方面映射另一个实体的 id。这些是相互冲突的要求。

最新更新