Example usage for javax.persistence SynchronizationType UNSYNCHRONIZED

List of usage examples for javax.persistence SynchronizationType UNSYNCHRONIZED

Introduction

In this page you can find the example usage for javax.persistence SynchronizationType UNSYNCHRONIZED.

Prototype

SynchronizationType UNSYNCHRONIZED

To view the source code for javax.persistence SynchronizationType UNSYNCHRONIZED.

Click Source Link

Document

Persistence context must be explicitly joined to the current transaction

Usage

From source file:org.springframework.orm.jpa.EntityManagerFactoryUtils.java

/**
 * Obtain a JPA EntityManager from the given factory. Is aware of a corresponding
 * EntityManager bound to the current thread, e.g. when using JpaTransactionManager.
 * <p>Same as {@code getEntityManager}, but throwing the original PersistenceException.
 * @param emf EntityManagerFactory to create the EntityManager with
 * @param properties the properties to be passed into the {@code createEntityManager}
 * call (may be {@code null})/* w  w w  .  j av  a 2s.co m*/
 * @param synchronizedWithTransaction whether to automatically join ongoing
 * transactions (according to the JPA 2.1 SynchronizationType rules)
 * @return the EntityManager, or {@code null} if none found
 * @throws javax.persistence.PersistenceException if the EntityManager couldn't be created
 * @see #getTransactionalEntityManager(javax.persistence.EntityManagerFactory)
 * @see JpaTransactionManager
 */
@Nullable
public static EntityManager doGetTransactionalEntityManager(EntityManagerFactory emf,
        @Nullable Map<?, ?> properties, boolean synchronizedWithTransaction) throws PersistenceException {

    Assert.notNull(emf, "No EntityManagerFactory specified");

    EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(emf);
    if (emHolder != null) {
        if (synchronizedWithTransaction) {
            if (!emHolder.isSynchronizedWithTransaction()) {
                if (TransactionSynchronizationManager.isActualTransactionActive()) {
                    // Try to explicitly synchronize the EntityManager itself
                    // with an ongoing JTA transaction, if any.
                    try {
                        emHolder.getEntityManager().joinTransaction();
                    } catch (TransactionRequiredException ex) {
                        logger.debug("Could not join transaction because none was actually active", ex);
                    }
                }
                if (TransactionSynchronizationManager.isSynchronizationActive()) {
                    Object transactionData = prepareTransaction(emHolder.getEntityManager(), emf);
                    TransactionSynchronizationManager
                            .registerSynchronization(new TransactionalEntityManagerSynchronization(emHolder,
                                    emf, transactionData, false));
                    emHolder.setSynchronizedWithTransaction(true);
                }
            }
            // Use holder's reference count to track synchronizedWithTransaction access.
            // isOpen() check used below to find out about it.
            emHolder.requested();
            return emHolder.getEntityManager();
        } else {
            // unsynchronized EntityManager demanded
            if (emHolder.isTransactionActive() && !emHolder.isOpen()) {
                if (!TransactionSynchronizationManager.isSynchronizationActive()) {
                    return null;
                }
                // EntityManagerHolder with an active transaction coming from JpaTransactionManager,
                // with no synchronized EntityManager having been requested by application code before.
                // Unbind in order to register a new unsynchronized EntityManager instead.
                TransactionSynchronizationManager.unbindResource(emf);
            } else {
                // Either a previously bound unsynchronized EntityManager, or the application
                // has requested a synchronized EntityManager before and therefore upgraded
                // this transaction's EntityManager to synchronized before.
                return emHolder.getEntityManager();
            }
        }
    } else if (!TransactionSynchronizationManager.isSynchronizationActive()) {
        // Indicate that we can't obtain a transactional EntityManager.
        return null;
    }

    // Create a new EntityManager for use within the current transaction.
    logger.debug("Opening JPA EntityManager");
    EntityManager em = null;
    if (!synchronizedWithTransaction) {
        try {
            em = emf.createEntityManager(SynchronizationType.UNSYNCHRONIZED, properties);
        } catch (AbstractMethodError err) {
            // JPA 2.1 API available but method not actually implemented in persistence provider:
            // falling back to regular createEntityManager method.
        }
    }
    if (em == null) {
        em = (!CollectionUtils.isEmpty(properties) ? emf.createEntityManager(properties)
                : emf.createEntityManager());
    }

    // Use same EntityManager for further JPA operations within the transaction.
    // Thread-bound object will get removed by synchronization at transaction completion.
    logger.debug("Registering transaction synchronization for JPA EntityManager");
    emHolder = new EntityManagerHolder(em);
    if (synchronizedWithTransaction) {
        Object transactionData = prepareTransaction(em, emf);
        TransactionSynchronizationManager.registerSynchronization(
                new TransactionalEntityManagerSynchronization(emHolder, emf, transactionData, true));
        emHolder.setSynchronizedWithTransaction(true);
    } else {
        // Unsynchronized - just scope it for the transaction, as demanded by the JPA 2.1 spec...
        TransactionSynchronizationManager
                .registerSynchronization(new TransactionScopedEntityManagerSynchronization(emHolder, emf));
    }
    TransactionSynchronizationManager.bindResource(emf, emHolder);

    return em;
}