title: JPA/Hibernate - Undesired Partial Rollback and Session Handling
body: <p>I am using a stateless EJB class to update a persistence entity located in a database. A method within the EJB calls an implementation class where the work is done. I believe what is causing the issue is that an entity called <code>Foo</code>, has a oneToMany relationship with an entity <code>Bar</code>. Things are done, and the Session is updated with <code>Foo</code> which 'cascades' to <code>Bar</code>. When a <code>StaleObjectStateException</code> occurs, the transaction is not being fully rolled back which is causing errors for obvious reasons. </p>
  
  <p><strong>EJB</strong>:</p>
  
  <pre><code>private Session getSession() throws BusinessException {
  
      if( this.sess == null ) {
              ServiceLocator locator = new ServiceLocator();
              SessionFactory sf = locator.getHibernateSessionFactory();
              this.sess = sf.openSession();
      }
      return this.sess;
  
  }
  
  private ProductionOrderImpl getImpl() throws BusinessException {
  
      if( this.impl == null ) {
          this.impl = new ProductionOrderImpl( getSession() );
      }
      return this.impl;
  
  }
  
  public void cutoffOrders(  ) throws Exception {
  
      Transaction tx = null;
      try {
          tx = getSession().beginTransaction();
          getImpl().cutOffFoos(fooTime);
          tx.commit();
      } catch (StaleObjectStateException e1){
          if (tx != null) tx.rollback();
          logger.error( "Failed to cutoff order : " + e1 );
          throw new Exception( LocaleMgr.getMessage());
      } 
        finally {
          // reset implementation object, close session,
          // and reset session object
          impl = null;
          sess.close();
          sess = null;
      }   
  }
  </code></pre>
  
  <p><strong>Implementation</strong>:</p>
  
  <pre><code>public ProductionOrderImpl(Session sess) {
      this.sess = sess;
  }
  
  public void cutoffFoos(  Timestamp fooTime) throws Exception {
      ... Code that gets fooList ...
      if( fooList != null ) {
          for( Foo foo: fooList ) {
              for( Bar bar : foo.getBarList() ) {
                   ... Code that does things with existing Barlist ...
                   if( ... ) {
                       ... Code that makes new Bar object ...
                       foo.getBarList().add(bar2);
                   }
              }
              sess.update( foo );
          }
      }
  }
  </code></pre>
  
  <p><strong>Relevant Foo code</strong>:</p>
  
  <pre><code>@OneToMany(cascade=CascadeType.ALL, mappedBy="foo")
  @OrderBy("startTime DESC")
  Set&lt;Bar&gt; barList;
  </code></pre>
  
  <p>So basically, when the Transaction tries to rollback, the Bar parts that were changed get rolled back, but the new Bar (bar2 in code) records remain..</p>
  
  <p>Any guidance would be appreciated. Like I said I believe the error here has to do with the <code>sess.update(foo)</code>; possibly something to do with <code>autocommit</code>, but by default it should be off.</p>
  
  <p>I believe that what is happening, is that the Session.Update(foo) is in turn creating two separate transactions. Specifically, the <code>Foo</code> is updated (SQL UPDATE), but the <code>Bar</code> is saved (SQL INSERT). Since the transaction context would only really see the SQL UPDATE, that is all it reverses. Will have to look into this more..</p>
  
  <p>I have tried changing the <code>Session.FlushMode</code> to <code>COMMIT</code> but it still doesn't seem to fix the issue. It does however, partially fix the problem.. It will rollback the entries properly except for the particular entry which causes the StaleObjectStateException. That particular entry is actually deleted right out of the database...</p>