Java 在没有em.flush()的情况下使用JPA持久化深层对象图
我有以下型号: 报告,, 报告部分和 ReportSectionProperty 报表具有零到多个ReportSection,ReportSection具有零到多个ReportSection属性。这将被称为三层深度对象图 我创建了一个新报告,然后向其中添加了一些部分,然后向其中添加了一些属性。当我尝试持久化报告时,出现以下错误:Java 在没有em.flush()的情况下使用JPA持久化深层对象图,java,orm,jpa,openjpa,Java,Orm,Jpa,Openjpa,我有以下型号: 报告,, 报告部分和 ReportSectionProperty 报表具有零到多个ReportSection,ReportSection具有零到多个ReportSection属性。这将被称为三层深度对象图 我创建了一个新报告,然后向其中添加了一些部分,然后向其中添加了一些属性。当我尝试持久化报告时,出现以下错误: Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: ERROR: insert or updat
Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: ERROR: insert or update on table "report_section" violates foreign key constraint "fk_report_section_report"
Detail: Key (id_node)=(186) is not present in table "report". {prepstmnt 20859482 INSERT INTO core.report_section (index_section, name, report_section_type, id_node) VALUES (?, ?, ?, ?) [params=?, ?, ?, ?]} [code=0, state=23503]
因此,OpenJPA是持久化对象图,但不知何故它是从中间开始的。id_节点186确实是报表表的下一个id,但显然,在保存ReportSection时不会保存该对象
如果我将em.persist(report)和em.flush()放在每次添加节或属性的操作之间,一切都会正常工作。这是路吗
如果我不向节添加任何属性,则即使没有em.flush(),持久化报告也可以工作
我使用OpenJPA2.0.3作为JPA提供者
可能代码的某些相关部分: Report.java
public class Report{
@OneToMany(targetEntity = ReportSection.class, cascade = CascadeType.ALL, mappedBy="report")
private List reportSections;
public void addReportSection(ReportSection section){
synchronized (this) {
if (getReportSections() == null)
reportSections = new ArrayList();
reportSections.add(section);
section.setReport(this);
}
}
}
ReportSection.java
public class ReportSection{
@ManyToOne
@JoinColumn(name="id_node")
private Report report;
@OneToMany(targetEntity=ReportSectionProperty.class, cascade=CascadeType.ALL, mappedBy="reportSection")
private List reportSectionProperties;
public void setReport(Report report) {
this.report = report;
}
public void addReportSectionProperty(ReportSectionProperty reportSectionProperty){
synchronized (this) {
if (getReportSectionProperties() == null)
reportSectionProperties = new ArrayList();
reportSectionProperties.add(reportSectionProperty);
reportSectionProperty.setReportSection(this);
}
}
}
公开课报告组{
@许多酮
@JoinColumn(name=“id\u节点”)
私人报告;
@OneToMany(targetEntity=ReportSectionProperty.class,cascade=CascadeType.ALL,mappedBy=“reportSection”)
私人财产清单;
公共作废报告(报告){
this.report=报告;
}
公共无效addReportSectionProperty(ReportSectionProperty ReportSectionProperty){
已同步(此){
如果(getReportSectionProperties()==null)
reportSectionProperties=new ArrayList();
reportSectionProperties.add(reportSectionProperty);
reportSectionProperty.setReportSection(本);
}
}
}
ReportSectionProperty
public class ReportSectionProperty{
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="id_report_section")
private ReportSection reportSection;
public void setReportSection(ReportSection reportSection) {
this.reportSection = reportSection;
}
}
公共类ReportSectionProperty{
@多通(级联=级联类型.ALL)
@JoinColumn(name=“id\u report\u section”)
私人报告科;
公共无效集合报告节(报告节报告节){
this.reportSection=reportSection;
}
}
如果我将em.persist(report)和em.flush()放在每次添加节或属性的操作之间,一切都会正常工作。这是路吗
如果定义了正确的级联设置,并且正确构造了双向关联(当然不包括任何JPA提供程序错误),那么这应该是不必要的。第一部分看起来不错。但我想看看你是如何完成最后一部分的。这可能是一条死线,但由于我面临类似的问题,我想展示我是如何解决它的,以供将来参考(如果有灵魂迷失,我必须处理OpenJPA) 尝试将此属性设置到persistence.xml中,以便OpenJPA可以按照正确的顺序重新排列sql语句 property name=“openjpa.jdbc.SchemaFactory”value=“native(ForeignKeys=true)”
您是否尝试将cascade=ALL添加到从ReportSection到Report的@ManyToOne关系中
在父报表对象上发布@Id属性也可能会有所帮助。谢谢您的回答。但是,我不知道你说“最后一部分”是指什么。你在考虑“正确构建双向关联”吗?我认为@OneToMany(mappedBy=…)和@ManyToOne注释涵盖了这一点。至少在阅读文档时我已经理解了这一点。您想获得所讨论的持久化场景的完整代码示例吗?也许值得注意的是,报表本身是节点的一种特殊化,它是模型中所有节点的基本抽象类。我正在使用InheritanceType.JOINED作为继承策略。@Rocky的“第一部分”指的是级联,“最后一部分”指的是双向链接的设置。但是,再看一眼(看看addXxx方法),它看起来是正确的(尽管我想知道为什么需要同步,但这是另一个故事)。但是,显示一些简单的代码来说明如何设置图形和
em.persist()
不会有任何影响。嗯,可能就是这样!我将在星期一试用,谢谢!:)