Note that there are some explanatory texts on larger screens.

plurals
  1. POPersisting deep object graph with JPA without em.flush()
    text
    copied!<p>I have following model:</p> <p><em>Report</em>, <em>ReportSection</em> and <em>ReportSectionProperty</em>.</p> <p><em>Report</em> has zero to many <em>ReportSections</em>, <em>ReportSection</em> has zero to many <em>ReportSectionPropert</em>-ies. This would qualifie as three levels deep object graph.</p> <p>I create new <em>Report</em>, then add some sections to it, then add some properties to it. When I try to persist <em>Report</em>, I get following error:</p> <pre><code>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]</code></pre> <p>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.</p> <p>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?</p> <p>If I don't add any properties to sections, persisting Report works, even without em.flush().</p> <p>I use OpenJPA 2.0.3 as JPA provider.</p> <hr> <p>Maybe some relevant parts of the code:</p> <p>Report.java</p> <pre><code>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); } } }</code></pre> <p>ReportSection.java</p> <pre>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); } } }</pre> <p>ReportSectionProperty</p> <pre>public class ReportSectionProperty{ @ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="id_report_section") private ReportSection reportSection; public void setReportSection(ReportSection reportSection) { this.reportSection = reportSection; } }</pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload