Question

I have a problem using mappers in mybatis-spring. (Spring Batch) I need to use a SqlSessionTemplate with ExecutorType in BATCH mode for performance issues (my program must execute thousands of insert statement in a table). However in my program I need to log errors and updating states in another table of the database and if something goes wrong in the execution of the current step everything is rollback, included the logs, which is not an acceptable behaviour. I thought I could simple set two different SqlSessionTemplate with differents ExecutorType, but if in my step I use two mappers with different templates I get an exception which says that I can't change ExecutorType during transaction, but I don't know how to solve this issue. Any help is appreciated. Here some XML configuration.

<!-- connect to database -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
    <property name="targetDataSource">
        <ref local="mainDataSource" />
    </property>
</bean> 


<bean id="mainDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.user}" />
    <property name="password" value="${db.pass}" />
</bean>

<bean id="infrastructureSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations"
        value="classpath*:com/generali/danni/sipo/mdv/dao/mybatis/*Mapper*.xml" />
    <property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>

<bean id="infrastructureSqlSessionTemplateBatch" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="infrastructureSqlSessionFactory" />
    <constructor-arg index="1" value="BATCH" />
</bean>

<bean id="infrastructureSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="infrastructureSqlSessionFactory" />
</bean>

    <bean id="infrastructureAbstractMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"
    abstract="true">
    <property name="sqlSessionTemplate" ref="infrastructureSqlSessionTemplate" /> 
</bean> 

<bean id="infrastructureAbstractMapperBatch" class="org.mybatis.spring.mapper.MapperFactoryBean"
    abstract="true">
    <property name="sqlSessionTemplate" ref="infrastructureSqlSessionTemplateBatch" />
</bean> 

<bean id="erroriMapper" parent="infrastructureAbstractMapper">
    <property name="mapperInterface"
        value="com.mdv.dao.ErroriMapper" />
</bean>

<bean id="stagingFileMapper" parent="infrastructureAbstractMapperBatch">
    <property name="mapperInterface"
        value="com.mdv.dao.StagingFileMapper" />
</bean>

Here i have two mappers, one I'd like to use in BATCH mode, the other in SIMPLE mode. How can I accomplish this task? Every suggestion is appreciated. Thanks in advance, and sorry for my bad english.

Was it helpful?

Solution

After a lot of tries, I decided to change my approach to solve this problem. I defined programmatically a new SqlSessionFactory, generating a new SqlSession with the Batch Executor and I used that one. Since it is an entirely different SqlSessionFactory, it seems it doesn't give problem if I use 2 differents ExecutorType. Here a sample working code:

Environment environment = new Environment("TEST", new JdbcTransactionFactory(), dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.addMappers("com.mdv.dao");

        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(configuration);
        SqlSession sqlSession = ssf.openSession(ExecutorType.BATCH);
        try {

            StagingFileMapper sfm = sqlSession.getMapper(StagingFileMapper.class);
            for(Record r : staging){
                StagingFile sf = new StagingFile();
                //set your sf fields
                sfm.insert(sf);
            }
            sqlSession.commit();
        } catch (Exception e) {
            //manage exception
        }
        finally{
            sqlSession.close();
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top