title: Persisting deep object graph with JPA without em.flush()
body: <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>