0

I expect the data to be written to the database after the method with @Transactional is completed. Is this a valid assumption for my JUnit test when using a HSQL database. I am using HSQL db for development and Oracle for my deployed application. Web App deployed on WebSphere, developed in RSA. Below is a summary of my configuration, including POM and junit test:

POM:
3.2.9.RELEASE
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.3</version>

<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.1</version>

APPLICATION CONTEXT:
<!-- the bean for transaction manager for scoping/controlling the transactions -->
<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dbDataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

<jee:jndi-lookup id="dbDataSource" jndi-name="jndi/HSQLDatasource" expected-type="javax.sql.DataSource" />

<!--Mapper-->
<bean id="campaignMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface"
        value="com.abc.persistence.mapper.CampaignMapper" />
    <property name="sqlSessionTemplate">
        <bean class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg index="0" ref="sqlSessionFactoryForBatch" />
            <constructor-arg index="1" value="BATCH" />
        </bean>
    </property>     
</bean>

<!-- SqlSessionFactory For Batch -->
<bean id="sqlSessionFactoryForBatch" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dbDataSource" />
    <property name="typeAliasesPackage" value="com.abc" />
    <property name="mapperLocations" value="classpath*:com/mybatis/mappers/**/*.xml" />
</bean>

JUNIT:
//junit class extends a base class that initializes HSQL db
//jdbcConnection.setAutoCommit(false);

    @Autowired
    CampaignMapper campaignMapper;

    @Transactional
    @Test 
    public void testInsert(){

        for(Campaign record:campaignsFromFile){
            record.setRowLastUpdateId(rowLastUpdateId);
            record.setCampaignId(campaignId);
            campaignMapper.insertCampaignRecord(record);
        }
        //At this point I expect that the data would NOT be written to the database
        //other method code

        }//end of method
        //At this point I expect that the data would be written to the database
Ali Dehghani
  • 46,221
  • 15
  • 164
  • 151
jimmy
  • 165
  • 1
  • 6
  • 18

1 Answers1

2

By default, Spring will rollback the transaction in test contexts. If this is not the behavior you expect, you always can use @Rollback annotation with false value:

@Transactional
@Test 
@Rollback(false)
public void testInsert() { ... }

If by any chance you're using Spring 4.2.x release, you can use the new @Commit annotation which is a new annotation that may be used as a direct replacement for @Rollback(false). You can read more about Transaction Management in Spring Test Context here.

Ali Dehghani
  • 46,221
  • 15
  • 164
  • 151
  • My expectation is that the records should not be written to to the database until after the method exits. However if I run in debug, put a break point after the insert and query the database after each insert (in the loop) I see the individual records written to the database one by one. My expectation is that they should be written only after the method completes. Thank you for the insight on @Rollback as it will be useful to know after I first correct this other issue. – jimmy Mar 30 '16 at 20:00
  • Then remove the `Transactional` and `Rollback` and manage transaction manually using `TestTransaction` abstraction. You can use `start`, `end` and `flagForCommit` methods. – Ali Dehghani Mar 30 '16 at 20:07
  • Sorry but now I'm confused. So I if I read this comment correctly cannot test my code as I intend to use it. I cannot use Transactional. I have to replace it with TestTranaction. I expected that this is a direct replacement annotation for Transactional for use in junit tests but this doesn't seem to be the case. I searched for help on TestTranaction but didn't get anything useful. If it is something completely different then I don't know how I can have confidence in my code when I deploy it if I cant inspect its behavior in my development environment. – jimmy Mar 30 '16 at 20:28
  • I guess I could connect my local appserver to oracle db and debug the code from there. Is that my only viable option. – jimmy Mar 30 '16 at 20:29