Sto utilizzando Spring/Spring-data-JPA e mi trovo a dover forzare manualmente un commit in un test di unità. Il mio caso d'uso è che sto facendo un test multi-thread in cui devo usare i dati che vengono mantenuti prima che i thread vengano spawnati.Come forzare manualmente un commit in un metodo @Transactional?
Sfortunatamente, poiché il test è in esecuzione in una transazione @Transactional
, anche un flush
non lo rende accessibile ai thread generati.
@Transactional
public void testAddAttachment() throws Exception{
final Contract c1 = contractDOD.getNewTransientContract(15);
contractRepository.save(c1);
// Need to commit the saveContract here, but don't know how!
em.getTransaction().commit();
List<Thread> threads = new ArrayList<>();
for(int i = 0; i < 5; i++){
final int threadNumber = i;
Thread t = new Thread(new Runnable() {
@Override
@Transactional
public void run() {
try {
// do stuff here with c1
// sleep to ensure that the thread is not finished before another thread catches up
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
threads.add(t);
t.start();
}
// have to wait for all threads to complete
for(Thread t : threads)
t.join();
// Need to validate test results. Need to be within a transaction here
Contract c2 = contractRepository.findOne(c1.getId());
}
Ho provato con il gestore di entità, ma un messaggio di errore quando lo faccio:
org.springframework.dao.InvalidDataAccessApiUsageException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead; nested exception is java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:293)
at org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:33)
C'è un modo per commettere la transazione e continuare? Non sono stato in grado di trovare alcun metodo che mi permetta di chiamare uno commit()
.
È possibile ricercare se esiste un modo per far partecipare i thread spawnati alla transazione in modo che vedano i risultati senza commit. –
Se il metodo è '@ Transactional', il ritorno dal metodo impegna la transazione. Quindi, perché non tornare indietro dal metodo? – Raedwald
Concettualmente i test unitari non dovrebbero probabilmente essere transazionali, e con il modello di Spring non ha alcun senso pratico. Dovresti esaminare i test di integrazione usando Spring TestContext che ha gli strumenti per aiutare nelle transazioni: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html # testing-tx –