使用JPA保留深层对象图而不使用em.flush()

时间:2010-09-15 13:09:42

标签: java orm jpa openjpa

我有以下型号:

报告的, ReportSection ReportSectionProperty

报告具有零到多个 ReportSections ReportSection 具有零到多个 ReportSectionPropert -ies。这将被定性为三级深度对象图。

我创建新的报告,然后向其中添加一些部分,然后向其添加一些属性。当我尝试持续报告时,我收到以下错误:

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_node 186确实是Report表的下一个id,但显然在保存ReportSection时不保存该对象。

如果我在添加部分或属性的每个操作之间放置em.persist(report)和em.flush(),那么一切正常。这是要走的路吗?

如果我没有向部分添加任何属性,那么即使没有em.flush(),持久化报告也能正常工作。

我使用OpenJPA 2.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);
        }
    }
}

ReportSectionProperty

public class ReportSectionProperty{

    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="id_report_section")
    private ReportSection reportSection;

    public void setReportSection(ReportSection reportSection) {
        this.reportSection = reportSection;
    }
}

3 个答案:

答案 0 :(得分:1)

这可能是一个死路线,但由于我遇到了类似的问题,我想表明我是如何设法解决它的,以备将来参考(如果任何失去的灵魂必须处理OpenJPA)

尝试将此属性设置为persistence.xml,以便OpenJPA可以按正确的顺序重新排列sql语句。

property name =“openjpa.jdbc.SchemaFactory”value =“native(ForeignKeys = true)”

http://openjpa.apache.org/faq.html#FAQ-CanOpenJPAreorderSQLstatementstosatisfydatabaseforeignkeyconstraints%253F

答案 1 :(得分:0)

  

如果我在添加部分或属性的每个操作之间放置em.persist(report)和em.flush(),那么一切正常。这是要走的路吗?

在定义适当的级联设置并正确构造双向关联时(当然不包括任何JPA提供程序错误),这不是必需的。第一部分看起来不错。但我想看看你如何做到最后一部分。

答案 2 :(得分:0)

您是否尝试将cascade = ALL添加到从ReportSection到Report的@ManyToOne关系?

将@Id属性也发布在父Report对象上可能会有所帮助。