Spring boot多数据源配置

674 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情 >>

前言

在日常开发中,我们一定会遇到与其他系统整合,或公司内部数据源不统一的情况,此时就需要在项目中配置多个数据源进行使用,那么如何配置一个多数据源呢?今天我将带来最简单的多数据源配置,这个方案还有很多缺点,比如代码冗余,代码重复度高,bean的作用一致浪费资源等。后续我还会带来动态切换数据源配置。

环境

  • JDK8
  • MYSQL 5.7
  • spring boot 2.67

项目结构

工程目录结构: image.png 注意:此项目比较简单的demo,省略了service层。Master为主数据源,Slave为分数据源

配置步骤

maven依赖

我这里使用了mybatis持久化框架

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.4.5</version>
</dependency>

配置文件

# master
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.jdbc-url=jdbc:mysql://11.11.11.11:3306/mds1?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.master.username=root
spring.datasource.master.password=111111

# slave
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.jdbc-url=jdbc:mysql://11.11.11.11:3306/mds2?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.slave.username=root
spring.datasource.slave.password=123312

我在服务器数据库中新建了两个库分别是mds1与mds2.服务器连接与密码需要改为自己的。 注意:在spring boot的多数据源中url需要是jdbc-url否则会报错的

配置类


@Configuration
@MapperScan(basePackages ="com.chp.mapper.MasterMapper" ,sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {

    // mapper.xml所在地址
    private static final String MAPPER_LOCATION = "classpath*:mapper/*.xml";


    /**
     * 主数据源,Primary注解必须增加,它表示该数据源为默认数据源
     * 项目中还可能存在其他的数据源,如获取时不指定名称,则默认获取这个数据源,如果不添加,则启动时候回报错
     */
    @Primary
    @Bean(name = "masterDataSource")
    // 读取spring.datasource.master前缀的配置文件映射成对应的配置对象
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource dataSource() {
        DataSource build = DataSourceBuilder.create().build();
        return build;
    }

    /**
     * 事务管理器,Primary注解作用同上
     */
    @Bean(name = "masterTransactionManager")
    @Primary
    public PlatformTransactionManager dataSourceTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * session工厂,Primary注解作用同上
     */

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource);
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MasterDataSourceConfig.MAPPER_LOCATION));
        return sessionFactoryBean.getObject();
    }

}

在配置类中的MapperScan中,需要配置自己对应的Mapper文件夹。在此项目中我将两个mapper文件夹分开了,一个是主mapper,一个是副mapper,对应哪个数据库的操作就写在哪个mapper中。 slave与master的文件一样,只是把master改为slave了,此处略

测试

在controller层中写测试代码,调用mapper的操作数据库的方法

image.png

image.png 由于是测试,我在两个数据库中新建的表是一样的 ,都是user表,里面有一个username。 调用接口后可以看到两个数据库分别插入了对应的数据

image.png

image.png

思考

其实这个方法个人感觉有很多不完美的地方,首先正如上文所说两个配置类一样,是可以被优化的,并且创建了两个bean实际可以用一个sqlsession。未来还会尝试动态切换数据库