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;
}
Aggregations