Hibernate 抛出 "NULL not allowed for column",因为在使用 @MapsId 时 SQL INSERT 中缺少 JPA OneToOne 关系 FK
Hibernate throws "NULL not allowed for column" as the JPA OneToOne relation FK is missing in the SQL INSERT when using @MapsId
关于我的 OneToOne 关系,我得到:
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),Hibernate 不会为外键使用一个单独的列。这就是插入查询不包含 user_id
列的原因。
最重要的是,CustomerOrderEntity 中的 id 一方面是 auto-generated(在超类中定义),另一方面映射另一个实体的 id。这些是相互矛盾的要求。
使用 @MapsId
允许您使用子 table 主键作为父 table 主键的外键。
如果启用 hbm2ddl
工具,您将看到 customer_order
table 将不包含 user_id
列。
但是,由于您之前生成了数据库架构并且您有一个带有专用 user_id
列的 customer_order
table,因此您需要删除 @MapsId
:
@OneToOne(fetch = FetchType.LAZY)
private UserEntity user;
这样,user
关联将使用 user_id
外键列。
关于我的 OneToOne 关系,我得到:
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),Hibernate 不会为外键使用一个单独的列。这就是插入查询不包含 user_id
列的原因。
最重要的是,CustomerOrderEntity 中的 id 一方面是 auto-generated(在超类中定义),另一方面映射另一个实体的 id。这些是相互矛盾的要求。
使用 @MapsId
允许您使用子 table 主键作为父 table 主键的外键。
如果启用 hbm2ddl
工具,您将看到 customer_order
table 将不包含 user_id
列。
但是,由于您之前生成了数据库架构并且您有一个带有专用 user_id
列的 customer_order
table,因此您需要删除 @MapsId
:
@OneToOne(fetch = FetchType.LAZY)
private UserEntity user;
这样,user
关联将使用 user_id
外键列。