MyBatis Operation Gets Blocked in Spring Boot Async Method
<p>In my project based on Spring Boot 1.3.3, I integrated MyBatis with mybatis-spring-boot-starter 1.1.1 as persistence layer, all CRUD operation seems working fine separately, but the integration tests failed and I found the DB operation gets blocked in asynchronous task.
The test code looks like this:</p>

<pre><code>@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SapiApplication.class)
@Transactional
public class OrderIntegrationTest {
    @Test
    public void shouldUpdateOrder() throws InterruptedException{
        Order order1 = getOrder1();
        orderService.createOrder(order1);

        Order order1updated = getOrder1Updated();
        orderService.updateOrderAsync(order1updated);

        Thread.sleep(1000l);

        log.info("find the order!");
        Order order1Db = orderService.findOrderById(order1.getOrderId());
        log.info("found the order!");
        assertEquals("closed", order1Db.getStatus());
    }
}
</code></pre>

<p>The expected execution order is createOrder() -> updateOrderAsync() -> findOrderById(), but actually the execution order is createOrder() -> updateOrderAsync() started and blocked -> findOrderById() -> updateOrderAsync() continued and ended.
Log:</p>

<pre><code>16:23:04.261 [executor1-1] INFO  c.s.api.web.service.OrderServiceImpl - updating order: 2884384
16:23:05.255 [main] INFO  c.s.a.w.service.OrderIntegrationTest - find the order!
16:23:05.280 [main] INFO  c.s.a.w.service.OrderIntegrationTest - found the order!
16:23:05.299 [executor1-1] INFO  c.s.api.web.service.OrderServiceImpl - updated order: 2884384
</code></pre>

<p>Other related code:</p>

<pre><code>@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;

    @Async("executor1")
    @Override
    public void updateOrderAsync(Order order){
        log.info("updating order: {}", order.getOrderId());
        orderDao.updateOrder(order);
        log.info("updated order: {}", order.getOrderId());
    }
}
</code></pre>

<p>The DAO:</p>

<pre><code>public interface OrderDao {
    public int updateOrder(Order order);
    public int createOrder(Order order);
    public Order findOrderById(String orderId);
}
</code></pre>

<p>The Gradle dependencies:</p>

<pre><code>dependencies {
    compile 'org.springframework.boot:spring-boot-starter-jdbc' 
    compile 'org.springframework.boot:spring-boot-starter-security' 
    compile 'org.springframework.boot:spring-boot-starter-web' 
    compile 'org.springframework.boot:spring-boot-starter-actuator'
    compile 'org.mybatis.spring.boot:mybatis-spring-boot-starter:1.1.1' 
    compile 'ch.qos.logback:logback-classic:1.1.2'
    compile 'org.springframework.boot:spring-boot-configuration-processor'
    runtime 'mysql:mysql-connector-java' 
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' 
    testCompile 'org.springframework.boot:spring-boot-starter-test'  
    testCompile "org.springframework.security:spring-security-test" 
}
</code></pre>

<p>The Spring configuration:</p>

<pre><code>@SpringBootApplication
@EnableAsync
@EnableCaching
@EnableScheduling
@MapperScan("com.sapi.web.dao")
public class SapiApplication {

@Bean(name = "executor1")
protected Executor taskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(100);
    return executor;
}

@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.primary")
public DataSource numberMasterDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean(name = "secondary")
@ConfigurationProperties(prefix = "datasource.secondary")
public DataSource provisioningDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean(name = "jdbcTpl")
public JdbcTemplate jdbcTemplate(@Qualifier("secondary") DataSource dsItems)   {
    return new JdbcTemplate(dsItems);
}

public static void main(String[] args) {
    SpringApplication.run(SapiApplication.class, args);
}
}
</code></pre>

<p>The properties:</p>

<pre><code>mybatis.mapper-locations=classpath*:com/sapi/web/dao/*Mapper.xml
mybatis.type-aliases-package=com.sapi.web.vo

datasource.primary.driver-class-name=com.mysql.jdbc.Driver
datasource.primary.url=jdbc:mysql://10.0.6.202:3306/sapi
datasource.primary.username=xxx
datasource.primary.password=xxx
datasource.primary.maximum-pool-size=80
datasource.primary.max-idle=10
datasource.primary.max-active=150
datasource.primary.max-wait=10000
datasource.primary.min-idle=5
datasource.primary.initial-size=5
datasource.primary.validation-query=SELECT 1
datasource.primary.test-on-borrow=false
datasource.primary.test-while-idle=true
datasource.primary.time-between-eviction-runs-millis=18800
datasource.primary.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=100)

datasource.secondary.url = jdbc:mysql://10.0.6.202:3306/xdb
datasource.secondary.username = xxx
datasource.secondary.password = xxx
datasource.secondary.driver-class-name = com.mysql.jdbc.Driver

logging.level.org.springframework.web=DEBUG
</code></pre>