Ich benutze Spring/Spring-Daten-JPA und finde mich gezwungen, ein Commit in einem Komponententest manuell erzwingen. Mein Anwendungsfall ist, dass ich einen Multithread-Test mache, bei dem ich Daten verwenden muss, die persistent sind, bevor die Threads erzeugt werden.Wie erzwinge manuell ein Commit in einer @ Transactional-Methode?
Leider, da der Test in einer @Transactional
-Transaktion ausgeführt wird, macht es auch eine flush
nicht zugänglich für die erzeugten Threads.
@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());
}
Ich habe versucht, den Entity Manager zu verwenden, aber eine Fehlermeldung zu erhalten, wenn ich tun:
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)
Gibt es eine Möglichkeit, die Transaktion und weiterhin zu begehen? Ich konnte keine Methode finden, die es mir erlaubt, eine commit()
anzurufen.
Sie könnten untersuchen, ob es eine Möglichkeit gibt, die erstellten Threads an der Transaktion teilnehmen zu lassen, damit die nicht festgeschriebenen Ergebnisse angezeigt werden. –
Wenn die Methode '@ Transactional' lautet, wird die Transaktion durch die Rückkehr von der Methode bestätigt. Warum also nicht einfach von der Methode zurückkehren? – Raedwald
Konzeptionelle Einheitentests sollten wahrscheinlich nicht transaktional sein, und mit dem Spring-Modell macht es auch keinen praktischen Sinn. Sie sollten Integrationstests mit Spring TestContext betrachten, der über Werkzeuge zur Unterstützung von Transaktionen verfügt: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/testing.html # testing-tx –