EntityManager - Truncate all data during test?

20 views Asked by At

I'm working with an older test setup where tests impacts each other and I'm trying to resolving this issue. I figured truncating all tables between the tests would do it but I can't seem to get the EM to play nicely with the command, this is how the relevant part of the code looks:

@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(...)
@ContextConfiguration(...)
public class MyTest {
    @PersistenceContext
    private EntityManager em;
    
    @After
    @Transactional // Current suite can't handle all tests being transactional
    public void after() {
        // ERROR: Method is not allowed for a query. Use execute or executeQuery instead of executeUpdate
        em.createNativeQuery("SELECT CONCAT('TRUNCATE TABLE ', TABLE_NAME, ';') FROM INFORMATION_SCHEMA.TABLES").executeUpdate(); 
    }
}

I understand that using executeUpdate() this way is a no-go but what options do I have that doesn't lead to me having to copy-paste a ton of rows where I do the delete per table explicitly?

1

There are 1 answers

0
David S On

I found a workaround to the issue, not the prettiest but at least works:

@Autowired
private EntityManagerFactory emf;

@After
public void after() {
    EntityManager em = emf.createEntityManager(); // Need to create a new EM as the one managed by @PersistenceContext has been closed when we get here
    Transaction transaction = ((Session) em.getDelegate()).beginTransaction();
    em.getMetamodel().getEntities().stream().map(Type::getJavaType).forEach(entity -> truncateTable(em, entity));
    transaction.commit();
    em.close();
}

private <T> void truncateTable(EntityManager em, Class<T> entity) {
    CriteriaBuilder criteria = em.getCriteriaBuilder();
    CriteriaDelete<T> deleteCriteria = criteria.createCriteriaDelete(entity);
    deleteCriteria.from(entity);
    em.createQuery(deleteCriteria).executeUpdate();
}