title: Why does Hibernate insert a parent row with a foreign key without inserting the child row?
body: <p>I'm hoping someone has run into this problem before and can help me out. Basically, Hibernate is inserting a parent row (with an ID pointing to a child row), but not inserting that child row with the associated ID, which leaves the database in a bad state. Here's an example of the exception that's thrown when Hibernate tries to load the improperly saved object:</p>
  
  <pre><code>27 Jun 2011 13:55:31,380 ERROR [scheduler_Worker-4] - 
  Job DEFAULT.queryScrubJobDetail threw an unhandled Exception: 
  org.springframework.scheduling.quartz.JobMethodInvocationFailedException: 
  Invocation of method 'doIt' on target class [XXX] failed; nested exception is
  org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException: 
  No row with the given identifier exists: 
  [XXX.DataProviderTransaction#60739703]; nested exception is org.hibernate.ObjectNotFoundException: 
  No row with the given identifier exists: 
  [com.idology.persist.DataProviderTransaction#2]
  </code></pre>
  
  <p>This part of the application has three entities:</p>
  
  <ul>
  <li><strong>Query</strong>, which is a parent of DataProviderTransactionReference and DataProviderTransaction</li>
  <li><strong>DataProviderTransaction</strong>, which is a child of Query and a parent of DataProviderTransactionReference</li>
  <li><strong>DataProviderTransactionReference</strong>, which has foreign keys pointing to DataProviderTransaction and Query</li>
  </ul>
  
  <p>Here are the mappings:</p>
  
  <p>From <strong>Query</strong>:</p>
  
  <pre><code>@OneToMany(mappedBy = "query", cascade =
      { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.LAZY)
  @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
  @JoinColumn(name = "query_id")
  public List&lt;DataProviderTransactionReference&gt; getDataProviderTransactionReferences()
  </code></pre>
  
  <p>From <strong>DataProviderTransaction</strong>:</p>
  
  <pre><code>@ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "query_id")
  public Query getQuery()
  </code></pre>
  
  <p>From <strong>DataProviderTransactionReference</strong>:</p>
  
  <pre><code>@ManyToOne(cascade =
      { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER)
  @JoinColumn(name = "data_provider_transaction_id")
  @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
  public DataProviderTransaction getDataProviderTransaction()
  {
      return mDataProviderTransaction;
  }
  </code></pre>
  
  <p>The schema looks like this (leaving out the queries table since it has no foreign keys):</p>
  
  <pre><code>data_provider_transaction
  
  +------------------+---------------+------+-----+---------+----------------+
  | Field            | Type          | Null | Key | Default | Extra          |
  +------------------+---------------+------+-----+---------+----------------+
  | id               | bigint(20)    | NO   | PRI | NULL    | auto_increment |
  | query_id         | bigint(20)    | YES  | MUL | NULL    |                |
  +------------------+---------------+------+-----+---------+----------------+
  
  data_provider_txn_refs
  
  +------------------------------+------------+------+-----+---------+----------------+
  | Field                        | Type       | Null | Key | Default | Extra          |
  +------------------------------+------------+------+-----+---------+----------------+
  | id                           | bigint(20) | NO   | PRI | NULL    | auto_increment |
  | created_at                   | datetime   | YES  |     | NULL    |                |
  | data_provider_transaction_id | bigint(20) | YES  | MUL | NULL    |                |
  | query_id                     | bigint(20) | YES  | MUL | NULL    |                |
  +------------------------------+------------+------+-----+---------+----------------+
  </code></pre>
  
  <p>So once we're done running a query (represented by the Query object), we save it using Spring and Hibernate using the following:</p>
  
  <pre><code>getHibernateTemplate().saveOrUpdate(aQuery);
  </code></pre>
  
  <p>The Query is saved along with the associated DataProviderTransaction and DataProviderTransactionReference entities. Except that sometimes it saves a Query and a DataProviderTransactionReference without the associated DataProviderTransaction. It does put an ID in the data_provider_transaction_id but it points to a row that does not exist in the data_provider_transaction table.</p>
  
  <p>The next step is to add a foreign key constraint to cause the problem to occur when we do the initial save rather than when we try to load the object later.</p>
  
  <p>We're using Spring 2.5.6, Hibernate 3.3.2, and MySQL 5.0. I've seen the problem occur over the years with earlier versions of Spring and Hibernate, though.</p>
  
  <p>Anyone ever seen/solved this problem?</p>