Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am doing unit testing and I expect that all data committed to the MySQL database will be rolled back... but this isn't the case. The data is being committed, even though my log was showing that the rollback was happening. I've been wrestling with this for a couple days so my setup has changed quite a bit, here's 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 have been reading about the issue, and I've already checked to ensure that the MySQL database tables are setup to use InnoDB. Also I have been able to successfully implement rolling back of transactions outside of my testing suite. So this must be some sort of incorrect setup on my part.

Any help would be greatly appreciated :)

like image 523
Trevor Avatar asked Nov 30 '22 10:11

Trevor


1 Answers

The problem turned out to be that the connection was auto-committing BEFORE the transaction could be rolled back. I had to change my dataSource bean to include a 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>
like image 154
Trevor Avatar answered Dec 05 '22 11:12

Trevor