29 August 2017

Immer wieder erlebe ich es, dass in Tests mit EntityManager Transaktionen gestartet und comitted werden. Allerdings gibt es kein Exception-Handling, sodass kein Rollback ausgeführt wird. Schlimmer noch: Die Transaktion wird nicht beendet und andere Tests schlagen ebenfalls fehl.

Um das zu verhindern, verwende ich ein solches Util:

public class TestUtil {
	public static <ENTITY_TYPE> ENTITY_TYPE getEntity(EntityManager entityManager, Class<ENTITY_TYPE> classType, Long id) {
		Query query = entityManager.createQuery("SELECT o FROM " + classType.getSimpleName() + " o");
		return (ENTITY_TYPE) query.getSingleResult();
	}

	public static <ENTITY_TYPE> void persistInTransaction(EntityManager entityManager, ENTITY_TYPE entity) {
		executeInTransaction(entityManager, () -> entityManager.persist(entity));
	}

	public static void executeInTransaction(EntityManager entityManager, TransactionExecutor transactionExecutor) {
		try {
			entityManager.getTransaction().begin();
			transactionExecutor.executeInTransaction();
			entityManager.getTransaction().commit();
		} catch (RuntimeException e) {
			if (entityManager.getTransaction().isActive()) {
				entityManager.getTransaction().rollback();
			}
			throw e;
		}
	}

	@FunctionalInterface
	public interface TransactionExecutor {
		void executeInTransaction();
	}
}