Hibernate - OneToMany ORA-02291 - 违反 - 找不到父键
Hibernate - OneToMany ORA-02291 - violated - parent key not found
我遇到错误:ORA-02291:完整性约束 - 违反 DESCRIPTOR__FK 从 JpaRepository
调用 .saveAll() 时未找到父键
我的数据库是 Oracle 18c
我在 FINDINGS 和 DESCRIPTOR 下面有 2 个表格。
1 个调查结果记录可以有多个描述符
create table FINDINGS
(
CLAIMNO VARCHAR2(50),
TRACEID VARCHAR2(50),
RULE VARCHAR2(10),
NUMBEROFFINDINGS INT,
constraint FINDINGS_PK
primary key (CLAIMNO, TRACEID)
)
/
create table DESCRIPTOR
(
TBL_ROW_ID int,
CLAIMNO VARCHAR2(50) not null,
TRACEID VARCHAR2(50) not null,
DESCRIPTOR VARCHAR2(4000),
constraint DESCRIPTOR_PK
primary key (CLAIMNO, TBL_ROW_ID, TRACEID),
constraint DESCRIPTOR__FK
foreign key (CLAIMNO, TRACEID) references FINDINGS
)
/
我的实体代码:
@Getter
@Setter
public class FindingsDOPK implements Serializable {
private static final long serialVersionUID = -7629886512750674550L;
private String claimno;
private String traceid;
}
@Getter
@Setter
public class DescriptorDOPK implements Serializable {
private static final long serialVersionUID = 5528285828768013262L;
private FindingsDO findingsDO;
private int tblRowId;
}
@Entity
@Getter
@Setter
@Table(name = "DESCRIPTOR")
@IdClass(DescriptorDOPK.class)
public class DescriptorDO implements Serializable {
private static final long serialVersionUID = 8951191961032280402L;
@Id
@Column(name = "TBL_ROW_ID")
private int tblRowId;
@Basic
@Column(name = "DESCRIPTOR")
private String descriptor;
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST }, optional = false)
@JoinColumns(
value = { @JoinColumn(name = "TRACEID", referencedColumnName = "CLAIMNO", nullable = false),
@JoinColumn(name = "CLAIMNO", referencedColumnName = "TRACEID", nullable = false) })
private FindingsDO findingsDO;
}
@Entity
@Setter
@Getter
@Table(name = "FINDINGS")
@IdClass(FindingsDOPK.class)
public class FindingsDO implements Serializable {
private static final long serialVersionUID = -3271206505226648660L;
@Id
@Column(name = "CLAIMNO")
private String claimno;
@Id
@Column(name = "TRACEID")
private String traceid;
@Basic
@Column(name = "RULE")
private String rule;
@Basic
@Column(name = "NUMBEROFFINDINGS")
private int numberoffindings;
@OneToMany(mappedBy = "findingsDO", fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
private Set<DescriptorDO> descriptorDOS;
}
我的java代码:
final List<FindingsDO> findingList = new ArrayList<>();
final var findingsDO = new FindingsDO();
findingsDO.setClaimno("123");
findingsDO.setTraceid("2e22a7b2-d1bb-41ff-9465-3d21da2a31");
findingsDO.setRule("RULE_123");
findingsDO.setNumberoffindings(1);
final Set<DescriptorDO> descriptorSet = new HashSet<>();
final var descriptorDO = new DescriptorDO();
descriptorDO.setTblRowId(1);
descriptorDO.setDescriptor("descriptor_1");
descriptorSet.add(descriptorDO);
for (final DescriptorDO descriptorDO : descriptorSet) {
descriptorDO.setFindingsDO(findingsDO);
}
findingsDO.setDescriptorDOS(descriptorSet);
findingList.add(findingsDO);
findingRepository.saveAll(findingList);
Hibernate 日志和按顺序生成的查询:
Hibernate: /* load FindingsDO */
select finding0_.TRACEID as traceid1_8_1_,
finding0_.CLAIMNO as claimno2_8_1_,
finding0_.NUMBEROFFINDINGS as numberoffindings3_8_1_,
finding0_.RULE as rule4_8_1_,
descrip1_.CLAIMNO as claimno3_7_3_,
descrip1_.TRACEID as traceid4_7_3_,
descrip1_.TBL_ROW_ID as tbl_row_id1_7_3_,
descrip1_.TBL_ROW_ID as tbl_row_id1_7_0_,
descrip1_.CLAIMNO as claimno3_7_0_,
descrip1_.TRACEID as traceid4_7_0_,
descrip1_.DESCRIPTOR as descriptor2_7_0_
from FINDINGS finding0_
left outer join DESCRIPTOR descrip1_
on finding0_.TRACEID = descrip1_.CLAIMNO and finding0_.CLAIMNO = descrip1_.TRACEID
where finding0_.TRACEID = ?
and finding0_.CLAIMNO = ?
Hibernate: /* load DescriptorDO */
select descrip0_.TBL_ROW_ID as tbl_row_id1_7_1_,
descrip0_.CLAIMNO as claimno3_7_1_,
descrip0_.TRACEID as traceid4_7_1_,
descrip0_.DESCRIPTOR as descriptor2_7_1_,
finding1_.TRACEID as traceid1_8_0_,
finding1_.CLAIMNO as claimno2_8_0_,
finding1_.NUMBEROFFINDINGS as numberoffindings3_8_0_,
finding1_.RULE as rule4_8_0_
from DESCRIPTOR descrip0_
inner join FINDINGS finding1_
on descrip0_.CLAIMNO = finding1_.TRACEID and descrip0_.TRACEID = finding1_.CLAIMNO
where descrip0_.TBL_ROW_ID = ?
and descrip0_.CLAIMNO = ?
and descrip0_.TRACEID = ?
Hibernate: /* insert FindingsDO */
insert into FINDINGS (NUMBEROFFINDINGS, RULE, TRACEID, CLAIMNO) values (?, ?, ?, ?)
Hibernate: /* insert DescriptorDO */
insert into DESCRIPTOR (DESCRIPTOR, TBL_ROW_ID, CLAIMNO, TRACEID) values (?, ?, ?, ?)
我该如何解决这个问题?
我通过将 CascadeType 更改为 CascadeType.ALL
来解决此问题
调查结果DO:
@OneToMany(mappedBy = "findingsDO", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<DescriptorDO> descriptorDOS;
描述符DO:
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumns(
value = { @JoinColumn(name = "TRACEID", referencedColumnName = "TRACEID", nullable = false),
@JoinColumn(name = "CLAIMNO", referencedColumnName = "CLAIMNO", nullable = false) })
private FindingsDO findingsDO;
我不确定背后的原因是什么,但我刚刚阅读了这篇文章,然后尝试使用 ALL 并且有效
https://www.baeldung.com/jpa-cascade-types
我遇到错误:ORA-02291:完整性约束 - 违反 DESCRIPTOR__FK 从 JpaRepository
调用 .saveAll() 时未找到父键我的数据库是 Oracle 18c
我在 FINDINGS 和 DESCRIPTOR 下面有 2 个表格。 1 个调查结果记录可以有多个描述符
create table FINDINGS
(
CLAIMNO VARCHAR2(50),
TRACEID VARCHAR2(50),
RULE VARCHAR2(10),
NUMBEROFFINDINGS INT,
constraint FINDINGS_PK
primary key (CLAIMNO, TRACEID)
)
/
create table DESCRIPTOR
(
TBL_ROW_ID int,
CLAIMNO VARCHAR2(50) not null,
TRACEID VARCHAR2(50) not null,
DESCRIPTOR VARCHAR2(4000),
constraint DESCRIPTOR_PK
primary key (CLAIMNO, TBL_ROW_ID, TRACEID),
constraint DESCRIPTOR__FK
foreign key (CLAIMNO, TRACEID) references FINDINGS
)
/
我的实体代码:
@Getter
@Setter
public class FindingsDOPK implements Serializable {
private static final long serialVersionUID = -7629886512750674550L;
private String claimno;
private String traceid;
}
@Getter
@Setter
public class DescriptorDOPK implements Serializable {
private static final long serialVersionUID = 5528285828768013262L;
private FindingsDO findingsDO;
private int tblRowId;
}
@Entity
@Getter
@Setter
@Table(name = "DESCRIPTOR")
@IdClass(DescriptorDOPK.class)
public class DescriptorDO implements Serializable {
private static final long serialVersionUID = 8951191961032280402L;
@Id
@Column(name = "TBL_ROW_ID")
private int tblRowId;
@Basic
@Column(name = "DESCRIPTOR")
private String descriptor;
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST }, optional = false)
@JoinColumns(
value = { @JoinColumn(name = "TRACEID", referencedColumnName = "CLAIMNO", nullable = false),
@JoinColumn(name = "CLAIMNO", referencedColumnName = "TRACEID", nullable = false) })
private FindingsDO findingsDO;
}
@Entity
@Setter
@Getter
@Table(name = "FINDINGS")
@IdClass(FindingsDOPK.class)
public class FindingsDO implements Serializable {
private static final long serialVersionUID = -3271206505226648660L;
@Id
@Column(name = "CLAIMNO")
private String claimno;
@Id
@Column(name = "TRACEID")
private String traceid;
@Basic
@Column(name = "RULE")
private String rule;
@Basic
@Column(name = "NUMBEROFFINDINGS")
private int numberoffindings;
@OneToMany(mappedBy = "findingsDO", fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
private Set<DescriptorDO> descriptorDOS;
}
我的java代码:
final List<FindingsDO> findingList = new ArrayList<>();
final var findingsDO = new FindingsDO();
findingsDO.setClaimno("123");
findingsDO.setTraceid("2e22a7b2-d1bb-41ff-9465-3d21da2a31");
findingsDO.setRule("RULE_123");
findingsDO.setNumberoffindings(1);
final Set<DescriptorDO> descriptorSet = new HashSet<>();
final var descriptorDO = new DescriptorDO();
descriptorDO.setTblRowId(1);
descriptorDO.setDescriptor("descriptor_1");
descriptorSet.add(descriptorDO);
for (final DescriptorDO descriptorDO : descriptorSet) {
descriptorDO.setFindingsDO(findingsDO);
}
findingsDO.setDescriptorDOS(descriptorSet);
findingList.add(findingsDO);
findingRepository.saveAll(findingList);
Hibernate 日志和按顺序生成的查询:
Hibernate: /* load FindingsDO */
select finding0_.TRACEID as traceid1_8_1_,
finding0_.CLAIMNO as claimno2_8_1_,
finding0_.NUMBEROFFINDINGS as numberoffindings3_8_1_,
finding0_.RULE as rule4_8_1_,
descrip1_.CLAIMNO as claimno3_7_3_,
descrip1_.TRACEID as traceid4_7_3_,
descrip1_.TBL_ROW_ID as tbl_row_id1_7_3_,
descrip1_.TBL_ROW_ID as tbl_row_id1_7_0_,
descrip1_.CLAIMNO as claimno3_7_0_,
descrip1_.TRACEID as traceid4_7_0_,
descrip1_.DESCRIPTOR as descriptor2_7_0_
from FINDINGS finding0_
left outer join DESCRIPTOR descrip1_
on finding0_.TRACEID = descrip1_.CLAIMNO and finding0_.CLAIMNO = descrip1_.TRACEID
where finding0_.TRACEID = ?
and finding0_.CLAIMNO = ?
Hibernate: /* load DescriptorDO */
select descrip0_.TBL_ROW_ID as tbl_row_id1_7_1_,
descrip0_.CLAIMNO as claimno3_7_1_,
descrip0_.TRACEID as traceid4_7_1_,
descrip0_.DESCRIPTOR as descriptor2_7_1_,
finding1_.TRACEID as traceid1_8_0_,
finding1_.CLAIMNO as claimno2_8_0_,
finding1_.NUMBEROFFINDINGS as numberoffindings3_8_0_,
finding1_.RULE as rule4_8_0_
from DESCRIPTOR descrip0_
inner join FINDINGS finding1_
on descrip0_.CLAIMNO = finding1_.TRACEID and descrip0_.TRACEID = finding1_.CLAIMNO
where descrip0_.TBL_ROW_ID = ?
and descrip0_.CLAIMNO = ?
and descrip0_.TRACEID = ?
Hibernate: /* insert FindingsDO */
insert into FINDINGS (NUMBEROFFINDINGS, RULE, TRACEID, CLAIMNO) values (?, ?, ?, ?)
Hibernate: /* insert DescriptorDO */
insert into DESCRIPTOR (DESCRIPTOR, TBL_ROW_ID, CLAIMNO, TRACEID) values (?, ?, ?, ?)
我该如何解决这个问题?
我通过将 CascadeType 更改为 CascadeType.ALL
来解决此问题调查结果DO:
@OneToMany(mappedBy = "findingsDO", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<DescriptorDO> descriptorDOS;
描述符DO:
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumns(
value = { @JoinColumn(name = "TRACEID", referencedColumnName = "TRACEID", nullable = false),
@JoinColumn(name = "CLAIMNO", referencedColumnName = "CLAIMNO", nullable = false) })
private FindingsDO findingsDO;
我不确定背后的原因是什么,但我刚刚阅读了这篇文章,然后尝试使用 ALL 并且有效 https://www.baeldung.com/jpa-cascade-types