Springboot Mybatis配置多数据源

134 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情

1.前言

在我们需要进行数据库连接的道路上,必定经历过很多弯路,时至今日,我们明白,必须配置连接池,让连接池来管理连接。另外,数据源真正应该做到的不是切换,而是多数据源同时存在。所以我们可以创建下面的数据源配置。

2.配置类

2.1.主配置类

主要配置类的作用就是为了启动时不报错,比如,我们的主数据源叫苹果数据源,它的配置如下:

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@MapperScan(basePackages = AppleDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "appleSqlSessionFactory")
@PropertySource(value = "classpath:databaseConfig.properties", ignoreResourceNotFound = true)
public class AppleDataSourceConfig
{
    static final String PACKAGE = "com.hengbao.common.dao.db.mapper.apple";
    static final String MAPPER_LOCATION = "classpath:com/hengbao/common/dao/db/map/apple/*.xml";
 
    @Value("${spring.datasource.apple.url}")
    private String url;
 
    @Value("${spring.datasource.apple.username}")
    private String user;
 
    @Value("${spring.datasource.apple.password}")
    private String password;
 
    @Value("${spring.datasource.apple.driver-class-name}")
    private String driverClass;
 
    @Bean(name = "appleDataSource")
    @Primary
    public DataSource appleDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }
 
    @Bean(name = "appleTransactionManager")
    @Primary
    public DataSourceTransactionManager appleTransactionManager() {
        return new DataSourceTransactionManager(appleDataSource());
    }
 
    @Bean(name = "appleSqlSessionFactory")
    @Primary
    public SqlSessionFactory appleSqlSessionFactory(@Qualifier("appleDataSource") DataSource appleDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(appleDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(AppleDataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }
}

这里需要解释一下:@Primary用来标记“主”,@MapperScan的属性直接配在这里的原因是,这是单独写两个数据源配置的写法,每个数据源要对应自己的包。@PropertySource是用来对应properties文件的,这样写的好处是,你不必将这个配置类放在必须有springboot启动类的项目里了,这样对于对应配置文件也比较方便。

2.2 其它数据源

如果需要香蕉数据源,我们就需要这样配置了:

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@MapperScan(basePackages = BananaDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "bananaSqlSessionFactory")
@PropertySource(value = "classpath:databaseConfig.properties", ignoreResourceNotFound = true)
public class BananaDataSourceConfig 
{
    static final String PACKAGE = "com.hengbao.common.dao.db.mapper.banana";
    static final String MAPPER_LOCATION = "classpath:com/hengbao/common/dao/db/map/banana/*.xml";
 
    @Value("${spring.datasource.banana.url}")
    private String url;
 
    @Value("${spring.datasource.banana.username}")
    private String user;
 
    @Value("${spring.datasource.banana.password}")
    private String password;
 
    @Value("${spring.datasource.banana.driver-class-name}")
    private String driverClass;
 
    @Bean(name = "bananaDataSource")
    public DataSource bananaDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClass);
        dataSource.setUrl(url);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }
 
    @Bean(name = "bananaTransactionManager")
    public DataSourceTransactionManager bananaTransactionManager() {
        return new DataSourceTransactionManager(bananaDataSource());
    }
 
    @Bean(name = "bananaSqlSessionFactory")
    public SqlSessionFactory bananaSqlSessionFactory(@Qualifier("bananaDataSource") DataSource bananaDataSource)
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(bananaDataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources(BananaDataSourceConfig.MAPPER_LOCATION));
        return sessionFactory.getObject();
    }
}

大家看到区别了吧,就是不写@Primary注解,这样的数据源配置多个是可以的,不过一般的,一个项目里也不会超过5个。需要连的数据源很多就要思考自己的架构和数据库设计了。

3.总结

当我们启动并测试这个配置的时候,假设我们配置了三个数据源,我们将会看到下面的输出:

2019-01-22 10:01:47.129  INFO 21104 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2019-01-22 10:01:47.316  INFO 21104 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2} inited
2019-01-22 10:01:47.417  INFO 21104 --- [           main] com.alibaba.druid.pool.DruidDataSource   : {dataSource-3} inited
2019-01-22 10:01:47.469  INFO 21104 --- [       Thread-2] com.alibaba.druid.pool.DruidDataSource   : {dataSource-3} closed
2019-01-22 10:01:47.474  INFO 21104 --- [       Thread-2] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} closed
2019-01-22 10:01:47.477  INFO 21104 --- [       Thread-2] com.alibaba.druid.pool.DruidDataSource   : {dataSource-2} closed

当然了,如果您并没有使用阿里巴巴的druid数据源,使用了其它的数据源,打印类路径会不同。