Search in sources :

Example 11 with TransactionRequiredException

use of javax.persistence.TransactionRequiredException in project spring-framework by spring-projects.

the class EntityManagerFactoryUtils method doGetTransactionalEntityManager.

/**
	 * 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})
	 * @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
	 */
public static EntityManager doGetTransactionalEntityManager(EntityManagerFactory emf, 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()) {
                    // 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 {
                // 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;
}
Also used : EntityManager(javax.persistence.EntityManager) TransactionRequiredException(javax.persistence.TransactionRequiredException)

Aggregations

TransactionRequiredException (javax.persistence.TransactionRequiredException)11 Test (org.junit.Test)10 PersistenceException (javax.persistence.PersistenceException)6 EntityManager (javax.persistence.EntityManager)5 Session (org.hibernate.Session)5 EntityExistsException (javax.persistence.EntityExistsException)1 EntityNotFoundException (javax.persistence.EntityNotFoundException)1 NoResultException (javax.persistence.NoResultException)1 NonUniqueResultException (javax.persistence.NonUniqueResultException)1 OptimisticLockException (javax.persistence.OptimisticLockException)1