Cascade 持久化具有未知 PK/FK 属性的 JPA 实体违反了 NotNullConstraint
Cascade persist JPA entities with unknown PK/FK attributes violates NotNullConstraint
我想保留一个具有许多 1:1 或 1:many 关系的 JPA 实体,只调用一次 persist
.
问题:实体的主键是自动生成的,并用作子实体的外键。提交事务时,出现异常,指出子实体的外键列上违反了 NotNullConstraint。
Internal Exception: java.sql.SQLException: ORA-01400: Insertion of
NULL in ("SCHEMA"."PROTOCOL_FILE"."PROTOCOL_ID") not possible
父实体:
@Entity
@Table(name = "...")
public class Protocol {
@Id
@GeneratedValue(generator="SQ_PROTOCOL", strategy=GenerationType.SEQUENCE)
@SequenceGenerator(name="SQ_PROTOCOL", sequenceName="SQ_PROTOCOL", allocationSize=50)
@Column(name = "PROTOCOL_ID")
private Long protocolId;
@OneToOne(mappedBy="protocol", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private ProtocolFile file;
//Other attributes and getter/setter omitted
}
子实体:
@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {
@Id
@Column(name = "PROTOCOL_ID")
private Long protocolId;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumns(@JoinColumn(name="PROTOCOL_ID", referencedColumnName="PROTOCOL_ID", updatable=false, insertable=false))
private Protocol protocol;
//Other attributes and getter/setter omitted
}
你知道一个方便的解决方案吗,这样我就可以在一次调用中保留属于 Protocol
的所有实体?
你这里的情况是 ProtocolFile
的 "derived identity" - ProtocolFile
的 ID 是 Protocol
的 ID,并且有一个 -它们之间是一对一的关系。
我看到您正在使用 updatable=false, insertable=false
,但最好遵循建议使用 @MapsId
注释的规范:
@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {
@Id // No @Column here
private Long protocolId;
@MapsId // --- HERE
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="PROTOCOL_ID") // Just that
private Protocol protocol;
}
或者您可能想完全跳过 protocolId
字段并在关系上添加 @Id
注释。
@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {
@Id // --- HERE
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="PROTOCOL_ID") // Just that
private Protocol protocol;
}
当然,您需要在创建时将 protocol
实例设置为 file
,以后不要再更改它(例如,只允许使用 ProtocolFile
设置它构造函数)。
有关更多详细信息和示例,请参阅 JPA 2.0 spec 的“2.4.1 对应于派生身份的主键”部分(示例 4 似乎是您的情况)。
我想保留一个具有许多 1:1 或 1:many 关系的 JPA 实体,只调用一次 persist
.
问题:实体的主键是自动生成的,并用作子实体的外键。提交事务时,出现异常,指出子实体的外键列上违反了 NotNullConstraint。
Internal Exception: java.sql.SQLException: ORA-01400: Insertion of NULL in ("SCHEMA"."PROTOCOL_FILE"."PROTOCOL_ID") not possible
父实体:
@Entity
@Table(name = "...")
public class Protocol {
@Id
@GeneratedValue(generator="SQ_PROTOCOL", strategy=GenerationType.SEQUENCE)
@SequenceGenerator(name="SQ_PROTOCOL", sequenceName="SQ_PROTOCOL", allocationSize=50)
@Column(name = "PROTOCOL_ID")
private Long protocolId;
@OneToOne(mappedBy="protocol", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private ProtocolFile file;
//Other attributes and getter/setter omitted
}
子实体:
@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {
@Id
@Column(name = "PROTOCOL_ID")
private Long protocolId;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumns(@JoinColumn(name="PROTOCOL_ID", referencedColumnName="PROTOCOL_ID", updatable=false, insertable=false))
private Protocol protocol;
//Other attributes and getter/setter omitted
}
你知道一个方便的解决方案吗,这样我就可以在一次调用中保留属于 Protocol
的所有实体?
你这里的情况是 ProtocolFile
的 "derived identity" - ProtocolFile
的 ID 是 Protocol
的 ID,并且有一个 -它们之间是一对一的关系。
我看到您正在使用 updatable=false, insertable=false
,但最好遵循建议使用 @MapsId
注释的规范:
@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {
@Id // No @Column here
private Long protocolId;
@MapsId // --- HERE
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="PROTOCOL_ID") // Just that
private Protocol protocol;
}
或者您可能想完全跳过 protocolId
字段并在关系上添加 @Id
注释。
@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {
@Id // --- HERE
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="PROTOCOL_ID") // Just that
private Protocol protocol;
}
当然,您需要在创建时将 protocol
实例设置为 file
,以后不要再更改它(例如,只允许使用 ProtocolFile
设置它构造函数)。
有关更多详细信息和示例,请参阅 JPA 2.0 spec 的“2.4.1 对应于派生身份的主键”部分(示例 4 似乎是您的情况)。