Why transactions are not rolled back when using SpringJUnit4ClassRunner / MySQL / Spring / Hibernate

I am doing unit testing and I expect that all the data transferred to the MySQL database will be thrown back ... but it is not. The data is captured, although my log shows that a rollback is occurring. I struggled with this for a couple of days, so my setup has changed quite a bit, here is my current setup.

LoginDAOTest.java:

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"file:web/WEB-INF/applicationContext-test.xml", "file:web/WEB-INF/dispatcher-servlet-test.xml"}) @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) public class UserServiceTest { private UserService userService; @Test public void should_return_true_when_user_is_logged_in () throws Exception { String[] usernames = {"a","b","c","d"}; for (String username : usernames) { userService.logUserIn(username); assertThat(userService.isUserLoggedIn(username), is(equalTo(true))); } } 

ApplicationContext-Text.xml:

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/******"/> <property name="username" value="*****"/> <property name="password" value="*****"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> <bean id="userService" class="Service.UserService"> <property name="userDAO" ref="userDAO"/> </bean> <bean id="userDAO" class="DAO.UserDAO"> <property name="hibernateTemplate" ref="hibernateTemplate"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>/himapping/User.hbm.xml</value> <value>/himapping/setup.hbm.xml</value> <value>/himapping/UserHistory.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory"/> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> </beans> 

I read about this issue, and I have already verified that the MySQL database tables are configured to use InnoDB. I also have the ability to successfully roll back transactions outside my test suite. So it should be some wrong setup on my part.

Any help would be greatly appreciated :)

+4
source share
5 answers

The problem turned out to be that the connection was an automatic commit BEFORE sending the transaction. I had to change my dataSource bean to include the defaultAutoCommit property:

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test"/> <property name="username" value="root"/> <property name="password" value="Ecosim07"/> <property name="defaultAutoCommit" value="false" /> </bean> 
+12
source

For me, defaultAutoCommit and @Transactional did not help. I had to change db type to InnoDB

+5
source

It is necessary to use

 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) @TestExecutionListeners({ TransactionalTestExecutionListener.class }) @Transactional 

TransactionalTestExecutionListener contains isRollback (), which rolls back the transaction after the testing method.

+1
source

I hope I'm right, and it's simple. You are missing the @Transactional annotation in your test class. This means that the test method itself is not executed in the transaction, and therefore rollback is not required. Hope this helps.

0
source

Another way to fix your problem:

Instead of using:

 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 

which by default creates the MyISAM table, therefore does not support transactions

Try using

 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> 

which creates InnoDB tables and thus supports transactions.

0
source

Source: https://habr.com/ru/post/1309678/


All Articles