0

I'm trying to migrate application which uses unsynchronized persistence context with JTA transaction, from hibernate 4.3.7 to Hibernate 5.0.7, and I found a couple the of issues I can't get my head around. Our entity manager injected as

@PersistenceContext(type = PersistenceContextType.EXTENDED, synchronization = SynchronizationType.UNSYNCHRONIZED)
private EntityManager entityManager;

So I expect to have extended and unsynchronized persistence context. The application uses UNSYNCHRONIZED feature to avoid flushing changes to the entities to the database until we want to do so. Normally, we want to flush changes only after save/persist/remove operations and these methods calling entityManager.joinTransaction(); to explicitly mark current transaction for synchronisation. This is used to work to a certain degree in Hibernate 4.3.7 but stopped in version 5.

For version 5, the Hiberante guys did quite a lot of rewriting, particularly in transaction handling area. From my understanding, hibernate uses session.autoJoinTransactions flag to implement UNSYNCHRONIZED feature. The session will not be flushed (we use default flushMode.AUTO) unless session joined to the transaction. Previously, this flag will be set for a new session as

sessionBuilder.autoJoinTransactions( getTransactionType() != PersistenceUnitTransactionType.JTA );

and in hibernate 5 (EntityManagetImpl line 132)

sessionBuilder.autoJoinTransactions( getSynchronizationType() == SynchronizationType.SYNCHRONIZED );

As we use JTA managed transactions it used to work. But now it does not. It seems that decide the value for autoJoinTransactionflag based on the SynchronizationType is the right thing to do, but there is one small problem. The persistenceContextTyoe is not propagated to the EntityFactoryImpl methods and therefore the entity manager always created as synchronised. When injecting the entityManager the wildlfy calling first method and not the second one.

@Override
    public EntityManager createEntityManager(Map map) {
        return internalCreateEntityManager( SynchronizationType.SYNCHRONIZED, map );
    }

    @Override
    public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
        errorIfResourceLocalDueToExplicitSynchronizationType();
        return internalCreateEntityManager( synchronizationType, map );
    }

So my questions: How to inject the instance of entity manager with Unsynchronized persistence context? Why Wildfly ignores type = PersistenceContextType.EXTENDED parameter when injecting entity manager? Am I missing something?

Bacteria
  • 8,406
  • 10
  • 50
  • 67
Mikhail Chibel
  • 1,865
  • 1
  • 22
  • 34

1 Answers1

0

As synchronisation type does propagate to the injected enntiyManager, I realised that I can use EntityManagerFactory to create entityManger. The factory has a method accepting synchronisation type so it will create unsynchronised context.

@PersistenceUnit
private EntityManagerFactory emf;
...
emf.createEntityManager(SynchronizationType.UNSYNCHRONIZED);

Also, I found that this issue logged against WildFly 8.1 https://issues.jboss.org/browse/WFLY-5006

Mikhail Chibel
  • 1,865
  • 1
  • 22
  • 34