I’m playing with technologies and framework for a new project: because I’m learning things probably useful for others, I’m gonna write here few notes about what I’ve learned. This is the fourth article of a series: we need to change MyBatis’ default configuration.

Part 4 – MyBatis configuration

In this article, I will change the default query executor (it is set to “simple”) using ExecutorType.BATCH: this setting is needed to boost the application performance.

Technologies used:

  • Java 8
  • MyBatis 3.3
  • Spring 4.2
  • Mybatis-Spring 1.2.3

Step 1 – Configuration file

As stated in its documentation, mybatis-spring needs a very minimal configuration file (that’s because, @MapperScan does a very good job in finding the mappers). An example of configuration could be the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="defaultExecutorType" value="BATCH"/>
    </settings>
</configuration>

I’ve named it modelConfig.xml and put it in src/main/resources directory.

Step 2 – Set config location in the SQL session factory

In the MybatisSpringConfig class, we have to change the following method, adding the call to setConfigLocation:

@Bean(name="sqlSessionFactory")
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(context.getBean(DataSource.class));
    sessionFactory.setConfigLocation(new ClassPathResource("modelConfig.xml"));
    sessionFactory.setTypeAliasesPackage("it.caladyon.db.model.generated.bita");
    return sessionFactory;
}

That’s it!

Step 3 – An alternative method that I prefer not to use

This is an alternative method to set the session’s executor type: it is done by source code, not configuration.

Be warned: I haven’t actually tested it… and I won’t, because it uses a BeanPostProcessor that needs the early initialization of the SqlSessionFactory bean, which I would like to avoid (I will write about that in a future article of this series, after having introduced the transactions).

Actually, the BeanPostProcessor is not mandatory, but however we need a way to inject the custom session into every mapper/dao.

For this method to work, we have to explicitly define an SqlSessionTemplate bean and a custom BeanPostProcessor (in a @Configuration class):

@Bean
public static MybatisSpringBeanPostProcessor mybatisSpringBeanPostProcessor() {
    return new MybatisSpringBeanPostProcessor();
}
@Bean
@Autowired
public SqlSessionTemplate sqlSession(ApplicationContext context) {
    return new SqlSessionTemplate(context.getBean(SqlSessionFactory.class), ExecutorType.BATCH);
}

The BeanPostProcessor implementation is:

public class MybatisSpringBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {

    private ApplicationContext context;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof SqlSessionDaoSupport) {
            ((SqlSessionDaoSupport) bean).setSqlSessionTemplate(context.getBean(SqlSessionTemplate.class));
        } else if (bean instanceof MapperFactoryBean) {
            ((MapperFactoryBean<?>) bean).setSqlSessionTemplate(context.getBean(SqlSessionTemplate.class));
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }
}

 

Annunci