Java 在没有em.flush()的情况下使用JPA持久化深层对象图

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

我有以下型号:

报告,, 报告部分和 ReportSectionProperty

报表具有零到多个ReportSection,ReportSection具有零到多个ReportSection属性。这将被称为三层深度对象图

我创建了一个新报告,然后向其中添加了一些部分,然后向其中添加了一些属性。当我尝试持久化报告时,出现以下错误:

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()
不会有任何影响。嗯,可能就是这样!我将在星期一试用,谢谢!:)