0

I'm trying to using transactionTemplate to manage my transaction. The code may list as below:

private Boolean isCleanSuccess(){
    return transactionTemplate.execute(new TransactionCallback<Boolean>() {
        @Override
        public Boolean doInTransaction(TransactionStatus transactionStatus) {
            String rmcName = "sync";
            StringBuilder sbSync = new StringBuilder();
            sbSync.append("delete from `t_sync_data_plan` WHERE 1=1");
            StringBuilder sbRmc = new StringBuilder();
            sbRmc.append("delete from `t_rmc_data` where `name`=\"")
                    .append(rmcName)
                    .append("\"");
            try{
                jdbcTemplate.execute(sbSync.toString());
                jdbcTemplate.execute(sbRmc.toString());
                /**
                  * throw the exception to make it rollback
                  */
                // throw new RuntimeException();
                return true;
            }catch (Exception ex){
                LOG.error(ex);
                transactionStatus.setRollbackOnly();
                return false;
            }
        }
    });
}

When I deal with Dao by using jdbcTemplate, it works. However, it just can not rollback if I throw the Exception when I use myBatis. The XML code lists as below:

<!-- rest transaction -->
<bean id="restTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="restDataSource"/>
</bean>

<bean id="restTransactionTemplate" name="restTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager" ref="restTransactionManager"/>
</bean>

 <!--domain transacation-->
<bean id="domainTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="domainDataSource"/>
</bean>

<bean id="domainTransactionTemplate" name="domainTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager">
        <ref bean="domainTransactionManager"/>
    </property>
</bean>

<!-- multi-datasource config -->
<bean id="multipleDataSource" class="com.angho.rest.db.MultipleDataSource" init-method="init">
    <property name="defaultTargetDataSource" ref="restDataSource"/>
    <property name="targetDataSources">
        <map>
            <entry key="restDataSource" value-ref="restDataSource"/>
            <entry key="domainDataSource" value-ref="domainDataSource"/>
        </map>
    </property>
    <property name="baseDaoDir" value="com.angho.rest"/>
    <property name="dataSourceNameMap">
        <map>
            <entry key="dao" value="restDataSource"/>
            <entry key="dao2" value="domainDataSource"/>
        </map>
    </property>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="multipleDataSource" />
    <property name="configLocation" value="classpath:/mybatis-config.xml"/>
</bean>

I don't know why the rollback just works under jdbcTemplate but loses efficacy under mybatis. The engine of table is InnoDB. Could you please give me a hand?It has been puzzled me for nearly two weeks. Sorry for the inconvenience that my poor English brought.

Merorin
  • 13
  • 4

1 Answers1

0

Try something like this:

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

...

@Value("${database.ip}")
private String databaseIp;

@Value("${database.user}")
private String user;

@Value("${database.password}")
private String password;

@Bean
public DataSource getMybatisDataSource() throws URISyntaxException {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");

    dataSource.setUrl("jdbc:mysql://"+databaseIp+":3306/swords");
    dataSource.setUsername(user);
    dataSource.setPassword(password);

    return dataSource;
}

@Bean
public DataSourceTransactionManager transactionManager() throws URISyntaxException {
    return new DataSourceTransactionManager(getMybatisDataSource());
}

@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(getMybatisDataSource());

    return sessionFactory.getObject();
}

This way you can simply use @Transacional.

More info: http://www.mybatis.org/spring/

Lakatos Gyula
  • 3,949
  • 7
  • 35
  • 56
  • Thanks for your answer. It seems that there is something wrong with 'multipleDataSource'.My workmate has just found the cause and made this bug fixed.Once upon a time, I'm also try to use @Transactional but my code style must be consistent with others'.Thank you anyway! – Merorin Jun 15 '16 at 02:53