How can I make an SqlSessionFactory uses specific TransactionManager?

852 Views Asked by At

For a set of multiple database, I successfully configured JDBC/JPA configurations.

@Db1 @Bean Datasource dataSourceDb1();
@Db1 @Bean AbstractEntityManagerFactoryBean entityManagerFactoryDb1(@Db1 DataSource);
@Db1 @Bean TransactionManager transactionManagerDb1(@Db1 DataSource);

@Db2 @Bean Datasource dataSourceDb2();
@Db2 @Bean AbstractEntityManagerFactoryBean entityManagerFactoryDb2(@Db2 DataSource);
@Db2 @Bean TransactionManager transactionManagerDb2(@Db2 DataSource);

As you can see all configurations are separated for each database.

Now I want to configure MyBatis for each databases.

I know I can produce an SqlSessionFactory like this.

    @Db1
    @Bean
    @ConfigurationProperties("application.db1.mybatis.configuration")
    org.apache.ibatis.session.Configuration mybatisConfigurationDb1() {
        return new org.apache.ibatis.session.Configuration();
    }

    @Db1
    @Bean
    public SqlSessionFactory sqlSessionFactoryDb1(
            @Db1 final DataSource dataSource,
            @Db1 final org.apache.ibatis.session.Configuration configuration) throws Exception {
        final SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setConfiguration(configuration);
        factoryBean.setVfs(SpringBootVFS.class); // // TODO: Check, works as expected? Required, actually?
        return factoryBean.getObject();
    }

My question is, How can I make above MyBatis configuration for @Db1 use the @Db1 transactionManagerDb1?

And, in a same way, make another MyBatis configuration for @Db2 use the @Db2 transactionManagerDb2?

1

There are 1 best solutions below

4
On BEST ANSWER

A SqlSessionFactory will use the transaction manager associated with the Datasource. MyBatis is using Spring's native transaction management so you can configure Datasources and transaction managers as is normal in Spring. The trick is to create multiple SqlSessionFactories and associate mappers to them.

The basic idea is to make two SqlSessionFactories and give them different names:

// configure Datasources and transaction managers as normal, then...

@Bean(name = "SessionFactory1")
public SqlSessionFactory sqlSessionFactory1(Datasource...) {
  ...
}

@Bean(name = "SessionFactory2")
public SqlSessionFactory sqlSessionFactory2(Datasource...) {
  ...
}

Then use the MapperScan annotation to attach different mappers to each factory:

@MapperScan(basePackages = "foo.bar.mapper1", sqlSessionFactoryRef = "SessionFactory1")
@MapperScan(basePackages = "foo.bar.mapper2", sqlSessionFactoryRef = "SessionFactory2")