title: FlushMode AUTO is not working with JPA and Hibernate
body: <p>We're currently migrating a legacy application written in <code>Spring/Hibernate</code> to <code>Spring Boot</code> (for having a less verbose config and other benefits). <br>
  Because <code>Spring Boot</code> adheres to <code>JPA</code>, we have to 'migrate' our legacy code - written in <code>native Hibernate</code> (version 5) - to <code>JPA</code>. <br><br>
  We're now facing an issue where Hibernate doesn't flush the session before firing a query, even when <code>FlushMode</code> is defined <code>AUTO</code></p>
  
  <p>Config looks as follows:</p>
  
  <p>1) Main Spring Boot Config that is the entry of the application</p>
  
  <pre><code>@Configuration
  @EnableAutoConfiguration
  @ComponentScan
  @Slf4j(topic = "system")
  public class MainApp {
      public static void main(String[] args) {
          SpringApplication.run(MainApp.class, args);
      }
  </code></pre>
  
  <p><br>2) Persistence Config: <br>
  - creates a <code>JPA Transaction Manager</code>;<br>
  - creates a <code>HibernateJpaSessionFactoryBean</code> to prevent we don't have to adapt all places where a <code>SessionFactory</code> is used (and autowired) by <code>EntityManagerFactory</code> and to ensure <code>SessionFactory</code> and <code>EntityManagerFactory</code> both participate in same (JPA) <code>Transaction</code>.</p>
  
  <pre><code>@Configuration
  public class PersistenceConfig {
    @Bean
      public PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
          JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactoryBean.getObject());
          transactionManager.setDefaultTimeout(30);
  
          return transactionManager;
      }
  
      @Bean
      public HibernateJpaSessionFactoryBean sessionFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
          HibernateJpaSessionFactoryBean sessionFactoryBean = new HibernateJpaSessionFactoryBean();
          sessionFactoryBean.setEntityManagerFactory(entityManagerFactoryBean.getObject());
  
          return sessionFactoryBean;
      }
   }
  </code></pre>
  
  <p><br>The responsible code that generates the issue is as follows:<br></p>
  
  <pre><code>@Override
  public void deletePossibleAnswerAndRemoveFromQuestion(Long definitionId, Long questionId, Long possibleAnswerId) {
      Definition definition = checkEntity(Definition.class, definitionId);
      Question question = checkEntity(Question.class, questionId);
      PossibleAnswer possibleAnswer = checkEntity(PossibleAnswer.class, possibleAnswerId);
  
      question.remove(possibleAnswer);
  
      if (definition.isHasRefinement()) {
           // this fires a 'select count(*) ...' query
          if (!possibleAnswerRepository.existsByType(definitionId, QuestionType.REFINE)) {
              definition.markNoRefinementsPresent();
          }
      }
  }
  </code></pre>
  
  <p><br>
  A PossibleAnswer (child) entity is removed from a Question (parent) entity by performing a cascading delete as shown in the code below:</p>
  
  <pre><code>@Table(name = "questions")
  @Entity
  @NoArgsConstructor(access = AccessLevel.PROTECTED)
  public class Question extends AbstractEntity {
  
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "question", cascade = CascadeType.ALL, orphanRemoval = true)
  private Set&lt;PossibleAnswer&gt; possibleAnswers = new HashSet&lt;&gt;();
  
  public void remove(PossibleAnswer possibleAnswer) {
      getPossibleAnswers().remove(possibleAnswer);
      possibleAnswer.setQuestion(null);
  }
  </code></pre>
  
  <p>The <code>remove</code> method is a convenience method that ensures both ends of bidirectional association are decoupled.</p>
  
  <p><br>
  The big problem now is that <code>question.remove(possibleAnswer)</code> is propagated to database just before commit time. <br>
  Put in other words: the cascading remove generates a delete query which is triggered <strong>after</strong> the 'count' query causing stale results as it depends on the PossibleAnswer being deleted. </p>
  
  <p>Things we checked:<br>
  1) <code>FlushMode</code> of the <code>Session</code> and default <code>FlushMode</code> of <code>SessionFactory</code>/<code>EntityManagerFactory</code> -> both are set to <code>AUTO</code> <br>
  2) Manually adding <code>session.flush()</code> before query is triggered -> this gives desired result where <code>question.remove(possibleAnswer)</code> is propagated to DB before firing query <br>
  3) We don't face the issue in our unit-test when running <code>native Hibernate</code></p>
  
  <p>Does anyone have a clue why we encounter this strange behavior???</p>
  
  <p>-- <strong>UPDATE 1</strong>-- 
  <br>
  Things I've checked: <br>
  1) Default FlushMode 'AUTO' is correctly set on EntityManager;<br>
  2) 'count' query is executed BEFORE cascading remove.
  <br><br>
  -- <strong>UPDATE 2</strong>-- 
  <br>
  It seems when the 'count' query is executed, Hibernate first checks (code depicted below) if the Session must be flushed before really executing the query. <br></p>
  
  <pre><code>    protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
      errorIfClosed();
      if ( !isTransactionInProgress() ) {
          // do not auto-flush while outside a transaction
          return false;
      }
      AutoFlushEvent event = new AutoFlushEvent( querySpaces, this );
      listeners( EventType.AUTO_FLUSH );
      for ( AutoFlushEventListener listener : listeners( EventType.AUTO_FLUSH ) ) {
          listener.onAutoFlush( event );
      }
      return event.isFlushRequired();
  }
  </code></pre>
  
  <p>The method <code>isTransactionInProgress</code>determines if a flush must be performed.
  The implementation looks like follows:</p>
  
  <pre><code>@Override
  public boolean isTransactionInProgress() {
      checkTransactionSynchStatus();
      return !isClosed() &amp;&amp; transactionCoordinator.getTransactionDriverControl()
              .getStatus() == TransactionStatus.ACTIVE &amp;&amp; transactionCoordinator.isJoined();
  }
  </code></pre>
  
  <p>It seems that
   <code>transactionCoordinator.getTransactionDriverControl().getStatus()</code> returns <code>NOT_ACTIVE</code> and <code>transactionCoordinator.isJoined()</code> returns <code>false</code>.
  <br><br>
  This is causing the issue that cascaded delete is not executed before firing the query. <br>
  I really don't have any idea why the underlying transaction is not is progress.
  <br>
  My setup is plain Spring Boot and Hibernate where I have a <code>Service</code> method annotated <code>@Transactional</code> so all underlying db-calls should be executed in one transaction.</p>