在提交中途使用AbstractTransactionalJUnit4SpringContextTests [英] Using AbstractTransactionalJUnit4SpringContextTests with commit halfway through
问题描述
我们想要一个运行多个线程的简单单元测试-这个想法是主线程将保存提交到数据库,然后等待辅助线程将其提取.
We want a simple unit test that runs multiple threads - the idea is that the main thread commits a save to the database, then waits for a secondary thread to pick it up.
我们发现必须为第二个线程提交事务才能查询数据库并找到项目.否则,它将不存在.
We're finding that the transaction has to be committed for the second Thread to be able to query the database and find the item. Otherwise, it won't exist.
我们正在尝试使用H2数据库来完成此任务,使用Hibernate来管理访问,并且单元测试扩展了AbstractTransactionalJUnit4SpringContextTests
.
We're trying to accomplish this using an H2 database, Hibernate to manage the access, and the unit test extends AbstractTransactionalJUnit4SpringContextTests
.
当我们尝试commit()
现有交易时:
When we try to commit()
the existing transaction:
... // Create and save our model object
sessionFactory.getCurrentSession().getTransaction().commit();
sessionFactory.getCurrentSession().beginTransaction();
... // Create and start second Thread, query, etc.
我们收到错误:
org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:484)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:521)`
但是当我们尝试仅扩展AbstractJUnit4SpringContextTests
并使用@Transactional
批注时:
But when we try to extend only AbstractJUnit4SpringContextTests
and use the @Transactional
annotations:
@TransactionConfiguration(defaultRollback=false, transactionManager="transactionManager")
@Transactional()
public class DatabaseIntegrityTest extends AbstractJUnit4SpringContextTests {
使用与上面相同的提交代码,我们将收到:
With the same commit code from above, we receive:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1041)
在我们第一次致电getCurrentSession()
期间.
During our first call to getCurrentSession()
.
是否可以通过JUnit Transactional Spring测试进行提交?
此外,当我们尝试使用AbstractTransactionalJUnit4SpringContextTests
创建自己的嵌套交易时,我们收到:
Further, when we try to create our own nested transaction using AbstractTransactionalJUnit4SpringContextTests
, we receive:
org.hibernate.TransactionException: nested transactions not supported
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1396)
编辑并添加答案:
由于axtavt
,我能够通过以下方式解决问题:
Thanks to axtavt
, I was able to fix things by:
1)扩展AbstractJUnit4SpringContextTests
2)对PlatformTransactionManager
使用@Autowired:
2) Using @Autowired for the PlatformTransactionManager
:
@Autowired
protected PlatformTransactionManager transactionManager;
3)将我的交易代码放入其中:
3) Putting my transactional code inside:
TransactionStatus status = transactionManager.getTransaction(null);
... // The Model-Saving Code
transactionManager.commit(status);
推荐答案
因此,您需要在测试方法内部创建多个事务.如您所见,您不能使用AbstractTransactionalJUnit4SpringContextTests
,因为它会为整个测试方法创建一个事务,而不能使用裸AbstractJUnit4SpringContextTests
,因为它根本不会创建任何事务.
So, you need to create multiple transactions inside your test method. As you can see, you cannot use AbstractTransactionalJUnit4SpringContextTests
, because it creates a single transaction for the whole test method, and cannot use bare AbstractJUnit4SpringContextTests
, because it creates no transactions at all.
解决方案是使用AbstractJUnit4SpringContextTests
并以编程方式管理测试方法中的事务.
The solution is to use AbstractJUnit4SpringContextTests
and manage transactions inside your test method programmatically.
您需要将PlatformTransactionManager
注入到测试中,从中创建TransactionTemplate
,并使用它按照
You need to inject PlatformTransactionManager
into your test, create TransactionTemplate
from it and use it to demarcate your transactions as described in 11.6 Programmatic transaction management.
这篇关于在提交中途使用AbstractTransactionalJUnit4SpringContextTests的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!