title: JPA many-to-many: unclear why join table is empty after persist
body: <p>I'm trying to implement simple Many-To-Many association using JPA (Hibernate 4) + Spring. Have seen tons of helloworld-like examples where join table is updated automatically when saving entities from 2 associated tables.</p>
  
  <p>However this is not happening in my case - even if I set bidirectional association and cascade, join table is not getting updated on <strong>em.persist()</strong>. While looking to why is this, I came to <a href="https://stackoverflow.com/a/3439748/1990089">this answer here at SO</a>, which suggests to use <strong>em.persist(); em.flush();</strong> to resolve this problem. I tried - miracle, persisting works fine! But... why??? </p>
  
  <p><strong>Questions:</strong></p>
  
  <ol>
  <li>Why should I use flush() here? </li>
  <li>Is this mentioned somewhere in official JPA/Hibernate documentation?</li>
  <li>Should I call flush() after each persist()/update()/remove() when working with many-to-many associations? What are possible downsides of such approach - performance, side effects? </li>
  </ol>
  
  <p>Here is related code.</p>
  
  <p>Entity classes</p>
  
  <pre><code>
  
      @Entity
      @Table(name="ROLE")
      public class Role extends EntityBase implements Comparable
      {   
         @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
         @JoinTable(name = "ROLE_PERMISSION", 
            joinColumns = @JoinColumn(name="role_id", referencedColumnName="id"),
            inverseJoinColumns = @JoinColumn(name="permission_id", referencedColumnName="id"))
         private Set permissions = new HashSet();
  
         //... other code (getters/setters/extra columns) is omitted ...
      }
  
      @Entity
      @Table(name="PERMISSION")
      public class Permission extends EntityBase
      {   
         @ManyToMany(mappedBy = "permissions", fetch = FetchType.LAZY)
         private Set roles = new HashSet();
  
         //... other code (getters/setters/extra columns) is omitted ...
      }
  
  </code></pre>
  
  <p>Generic DAO implementation (being used by my concrete DAOs):</p>
  
  <pre><code>
  
      @Repository
      @Transactional(value="transactionManager")
      public abstract class GenericDaoImpl implements GenericDao
      {  
         @PersistenceContext(unitName = "entityManagerFactory")
         protected EntityManager em;
  
         public T create( final T t )
         {
            em.persist(t);
            // em.flush(); - if I put this here, all works well (and fails if I'm not)
            return t;
         }
  
         // ... other code is omitted ...
      }
  
  </code></pre>
  
  <p>Service layer method which I'm trying to test:</p>
  
  <pre><code>
  
      @Component("securityService")
      public class SecurityServiceImpl implements SecurityService
      {
         // ... other code is omitted ...   
  
         @Transactional(value="transactionManager", 
            rollbackFor = Exception.class, readOnly = false)
         public void createRole( Role role )
         {
            Validate.notNull( role, "Role should not be null" );
            roleDao.create( role );
         }
      }
  
  </code></pre>
  
  <p>And finally my TestNG integration test (uses in-memory H2 DB):</p>
  
  <pre><code>
  
      @ContextConfiguration(
         locations={"/META-INF/beans-test.xml"})
      @TransactionConfiguration(
         transactionManager = "transactionManager", defaultRollback = true)
      public class SecurityServiceImplIT 
         extends AbstractTransactionalTestNGSpringContextTests
      {
         @Autowired
         @Qualifier("securityService")
         private SecurityService securityService;
  
         @Test
         @Transactional(value = "transactionManager")
         public void createRole_createRoleWithPermissions()
         {
            // Add test data to DB.
            super.executeSqlScript( TESTDATA_PATH, false);
            // Remove all associations between permissions and roles, need
            // clear intermediate table for this test case.
            super.simpleJdbcTemplate.update( 
               "delete from DB_TEST.ROLE_PERMISSION;" );
            super.simpleJdbcTemplate.update( 
               "delete from DB_TEST.ROLE;" );
  
            final Role role = new Role();
            role.setName( "Test role" );
            role.addPermission( securityService.getAllPermissions().get(0) );
            final int expectedPermissionCount = 1;
  
            securityService.createRole(role);
  
            // This is always passed
            Assert.assertEquals( super.countRowsInTable( "DB_TEST.ROLE" ), 1, 
               "New role should be added, so table should contain 1 row" );
  
            // This is failed if I'm not using flush() in my DAO.
            Assert.assertEquals( super.countRowsInTable( "DB_TEST.ROLE_PERMISSION" ), 
               expectedPermissionCount, "Role-permission associations should be added" );
         }
  
         // ... other code is omitted ...
      }
  
  </code></pre>
  
  <p>Hibernate debug log (without flush() call in DAO):</p>
  
  <pre>
  Hibernate: insert into DB_TEST.ROLE (id, version, description, name) values (null, ?, ?, ?)
  
  ...
  
  aa TRACE org.hibernate.engine.jdbc.internal.LogicalConnectionImpl: Starting after statement execution processing [ON_CLOSE]
  aa TRACE org.hibernate.action.internal.UnresolvedEntityInsertActions: No unresolved entity inserts that depended on [[xxx.logic.db.model.Role#4]]
  aa TRACE org.hibernate.engine.internal.Cascade: Processing cascade ACTION_PERSIST_SKIPLAZY for: xxx.logic.db.model.Role
  aa TRACE org.hibernate.engine.internal.Cascade: Cascade ACTION_PERSIST_SKIPLAZY for collection: xxx.logic.db.model.Role.permissions
  aa TRACE org.hibernate.engine.spi.EJB3CascadingAction: Cascading to persist: xxx.logic.db.model.Permission
  aa TRACE org.hibernate.event.internal.AbstractSaveEventListener: Persistent instance of: xxx.logic.db.model.Permission
  aa TRACE org.hibernate.event.internal.DefaultPersistEventListener: Ignoring persistent instance
  aa TRACE org.hibernate.engine.internal.Cascade: Done cascade ACTION_PERSIST_SKIPLAZY for collection: xxx.logic.db.model.Role.permissions
  aa TRACE org.hibernate.engine.internal.Cascade: Done processing cascade ACTION_PERSIST_SKIPLAZY for: xxx.logic.db.model.Role
  aa TRACE org.hibernate.action.internal.UnresolvedEntityInsertActions: No entity insert actions have non-nullable, transient entity dependencies.aa TRACE org.hibernate.engine.jdbc.internal.LogicalConnectionImpl: Starting after statement execution processing [ON_CLOSE]
  aa TRACE org.hibernate.action.internal.UnresolvedEntityInsertActions: No unresolved entity inserts that depended on [[xxx.logic.db.model.Role#4]]
  aa TRACE org.hibernate.engine.internal.Cascade: Processing cascade ACTION_PERSIST_SKIPLAZY for: xxx.logic.db.model.Role
  aa TRACE org.hibernate.engine.internal.Cascade: Cascade ACTION_PERSIST_SKIPLAZY for collection: xxx.logic.db.model.Role.permissions
  aa TRACE org.hibernate.engine.spi.EJB3CascadingAction: Cascading to persist: xxx.logic.db.model.Permission
  aa TRACE org.hibernate.event.internal.AbstractSaveEventListener: Persistent instance of: xxx.logic.db.model.Permission
  aa TRACE org.hibernate.event.internal.DefaultPersistEventListener: Ignoring persistent instance
  aa TRACE org.hibernate.engine.internal.Cascade: Done cascade ACTION_PERSIST_SKIPLAZY for collection: xxx.logic.db.model.Role.permissions
  aa TRACE org.hibernate.engine.internal.Cascade: Done processing cascade ACTION_PERSIST_SKIPLAZY for: xxx.logic.db.model.Role
  aa TRACE org.hibernate.action.internal.UnresolvedEntityInsertActions: No entity insert actions have non-nullable, transient entity dependencies.
  
  </pre>
  
  <p>This log is saying that Hibernate is going through the Permissions collection, but ignoring items from there for some reason. I totally don't understand why calling flush() makes any difference here... Generally, flush() is just an ability to explicitly tell Hibernate when to post SQL query to DB. </p>
  
  <p>Can anyone explain this or at least point me to right documentation?</p>