I'm having problem trying to push changes made within a Hibernate transaction to the database for DbUnit to work properly in my test case. It seems like DbUnit is not seeing the changes made by Hibernate because they are not committed at the end of the transaction yet... and I'm not sure how to restructure my test case to get this to work.
Here's my over-simplified test case to demonstrate my problem:-
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:applicationContext-test.xml"
})
@TransactionConfiguration(transactionManager = "transactionManager")
@Transactional
public class SomeTest {
@Autowired
protected DataSource dataSource;
@Autowired
private SessionFactory sessionFactory;
@Test
public void testThis() throws Exception {
Session session = sessionFactory.getCurrentSession();
assertEquals("initial overlayType count", 4, session.createQuery("from OverlayType").list().size());
//-----------
// Imagine this block is an API call, ex: someService.save("AAA");
// But for the sake of simplicity, I do it this way
OverlayType overlayType = new OverlayType();
overlayType.setName("AAA");
session.save(overlayType);
//-----------
// flush has no effect here
session.flush();
assertEquals("new overlayType count", 5, session.createQuery("from OverlayType").list().size());
// pull the data from database using dbunit
IDatabaseConnection connection = new DatabaseConnection(dataSource.getConnection());
connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());
QueryDataSet partialDataSet = new QueryDataSet(connection);
partialDataSet.addTable("resultSet", "select * from overlayType");
ITable actualTable = partialDataSet.getTable("resultSet");
// FAIL: Actual row count is 4 instead of 5
assertEquals("dbunit's overlayType count", 5, actualTable.getRowCount());
DataSourceUtils.releaseConnection(connection.getConnection(), dataSource);
}
}
My whole idea in using DbUnit is to:-
someService.save(...)
that saves data into several tables.Assertion.assertEquals(expectedTable, actualTable);
.But, at this point, I'm not able to get DbUnit to see the changes made by Hibernate within the transaction.
How should I change to get DbUnit to work nicely with Hibernate transaction?
Thanks.
Transaction Interface in Hibernate In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC). A transaction is associated with Session and instantiated by calling session.
Therefore, you can run multiple transactions on the same Hibernate Session, but there's a catch. Once an exception is thrown you can no longer reuse that Session. My advice is to divide-and-conquer. Just split all items, construct a Command object for each of those and send them to an ExecutorService#invokeAll .
@Transactional spans the transaction for entire test method, so if you use some dao (like in your case) that transaction will be rolledback also, however if some method uses transaction propagation type other than REQUIRED , for example REQUIRED_NEW , call to db can be performed anyway, because REQUIRED_NEW suspends ...
In Hibernate, the transaction management is quite standard, just remember any exceptions thrown by Hibernate are FATAL, you have to roll back the transaction and close the current session immediately.
I have never worked with DbUnit, but it seems like TransactionAwareDataSourceProxy
will do the trick. Basically you need to wrap your original data source with this proxy and use it instead, so that this code:
new DatabaseConnection(dataSource.getConnection())
actually goes through the proxy and uses the same transaction and connection as Hibernate.
I found Transaction aware datasource (use dbunit & hibernate in spring) blog post explaining this.
Another approach would be to skip transactional tests altogether and cleanup the database instead manually. Check out my transactional tests considered harmful artcle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With