如何在@Transactional方法中手动强制提交? [英] How to manually force a commit in a @Transactional method?
问题描述
我正在使用Spring / Spring-data-JPA,并发现自己需要在单元测试中手动强制提交。我的用例是我正在进行多线程测试,我必须使用在生成线程之前保留的数据。
I'm using Spring / Spring-data-JPA and find myself needing to manually force a commit in a unit test. My use case is that I am doing a multi-threaded test in which I have to use data that is persisted before the threads are spawned.
不幸的是,考虑到测试正在 @Transactional
事务中运行,即使 flush
也不会使生成的线程可以访问它。
Unfortunately, given that the test is running in a @Transactional
transaction, even a flush
does not make it accessible to the spawned 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());
}
我尝试过使用实体管理器,但收到错误消息时我这样做:
I've tried using the entity manager to, but get an error message when I do:
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)
有没有办法提交交易并继续交易?我一直无法找到允许我调用 commit()
的方法。
Is there any way to commit the transaction and continue it? I have been unable to find any method that allows me to call a commit()
.
推荐答案
在测试hibernate事件监听器时我有一个类似的用例,它只在commit上调用。
I had a similar use case during testing hibernate event listeners which are only called on commit.
解决方案是将代码保存到另一个用 REQUIRES_NEW
注释的方法中。 (在另一个类中)这样生成一个新事务,并在方法返回后发出flush / commit。
The solution was to wrap the code to be persistent into another method annotated with REQUIRES_NEW
. (In another class) This way a new transaction is spawned and a flush/commit is issued once the method returns.
请记住,这可能会影响所有其他测试!因此,请相应地编写它们,或者您需要确保在测试运行后可以进行清理。
Keep in mind that this might influence all the other tests! So write them accordingly or you need to ensure that you can clean up after the test ran.
这篇关于如何在@Transactional方法中手动强制提交?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!