简体   繁体   中英

Persisting deep object graph with JPA without em.flush()

I have following model:

Report , ReportSection and ReportSectionProperty .

Report has zero to many ReportSections , ReportSection has zero to many ReportSectionPropert -ies. This would qualifie as three levels deep object graph.

I create new Report , then add some sections to it, then add some properties to it. When I try to persist Report , I get following error:

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]

So, OpenJPA is persisting object graph, but somehow it started from the middle. id_node 186 is indeed the next id of the Report table but, obviously that object is not saved when ReportSection is being saved.

If I put em.persist(report) then em.flush() between each operation of adding sections or properties, everything works. Is this the way to go?

If I don't add any properties to sections, persisting Report works, even without em.flush().

I use OpenJPA 2.0.3 as JPA provider.


Maybe some relevant parts of the code:

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;
    }
}

This might be a dead thread, but since i faced a similar issue i would like to show how i managed to resolved it, for future references (in case of any lost soul have to deal with OpenJPA)

Try to set this property into your persistence.xml so OpenJPA can rearrange the sql statement in the correct order.

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

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

If I put em.persist(report) then em.flush() between each operation of adding sections or properties, everything works. Is this the way to go?

This shouldn't be necessary with proper cascading settings defined and with bidirectional associations properly constructed (excluding any JPA provider bug of course). The first part looks OK. But I'd like to see how you do the last part.

Did you try adding cascade=ALL to the @ManyToOne relationship from ReportSection to Report?

It might help to post your @Id property on the parent Report object as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM