SpringBoot配置多数据源(mybatis+druid)

序言

一个SpringBoot项目在某些情境下需要配置多个数据源(数据库),我是在一个单体应用中,使用领域驱动的思想设计的时候所遇到的问题。由于初代版本仅跑在单个服务器上,无法用微服务框架,故仅能将数据库分成三个并与同一个springboot项目连接。踩了不少雷总结出的一些经验。
请注意:我默认读者会使用IDEA创建SpringBoot项目,并拥有MyBatis的使用经验

首先声明我所有用到的maven的版本(貌似并不是很重要)

  1. idea 2020.1
  2. MySQL 8.0
  3. mybatis-spring-boot-starter 2.2.1
  4. java SE 1.8
  5. SpringBoot 2.6.2
  6. Druid 1.1.10

正文开始

下面画圈部分是本次配置所需配置的文件

  1. config包内是本次的核心配置类,一个数据源对应一个类(重点
  2. repository包存放着MyBatis所提供的mapper接口类
  3. mapper包存放着MyBatis提供的接口类所对应的XML文件
  4. yml就是SpringBoot的配置文件

提前梳理一下数据源与这几个包文件的对应关系(敲黑板)
一个数据源对应config包的一个类,对应repository包下面的其中一个包,对应mapper包下面的一个包,对应yml文件中配置的一个数据源
SpringBoot配置多数据源(mybatis+druid)_第1张图片
有了上面的总述,下面就来一步步的去具体实现

1.首先是yml文件,其中请务必关注三个注释下面的三个不同的数据源的名字,因为下一步是手动获取yml文件的配置,并非自动配置。

spring:
  mybatis:
    mapper-locations: classpath:mapper/*Mapper.xml
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    #homework数据源
    homework:
      druid:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/spoc_homework?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
        initial-size: 5
        min-idle: 5
        max-active: 50
    #course数据源
    course:
      druid:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/spoc_course?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
        initial-size: 5
        min-idle: 5
        max-active: 50
    #user数据源
    user:
      druid:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/spoc_user?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
        initial-size: 5
        min-idle: 5
        max-active: 50
server:
  port: 80

2.再创建config包,这个只要让SpringBoot扫描到就行,并不需要在启动类上特别加注释
以其中两个类DataSourceCourse、DataSourceUser 为例。

/**
 * @Author: STY
 *@Date:2022/1/27
 *@Describe:user数据源配置类
 * */
@Configuration
@MapperScan(basePackages = "com.example.spoc.repository.user.mapper", sqlSessionTemplateRef = "userSqlSessionTemplate")
public class DataSourceUser {
    @Value("${spring.datasource.user.druid.url}")
    private String url;
    @Value("${spring.datasource.user.druid.username}")
    private String username;
    @Value("${spring.datasource.user.druid.password}")
    private String password;
    @Value("${spring.datasource.user.druid.driverClassName}")
    private String driverClassName;
    @Bean("userDataSource")
    @Primary
    public DruidDataSource dataSource()
    {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(this.url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        System.out.println("user");
        return datasource;
    }
    @Bean("userSqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/userMapper/*Mapper.xml"));
        return sessionFactory.getObject();
    }

    @Bean("userTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("userDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("userSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
/**
 1. @Author: STY
*@Date:2022/1/27
*@Describe:Course数据源配置类
 2. */
@Configuration
@MapperScan(basePackages = "com.example.spoc.repository.course.mapper", sqlSessionTemplateRef = "courseSqlSessionTemplate")
public class DataSourceCourse {
    @Value("${spring.datasource.course.druid.url}")
    private String url;
    @Value("${spring.datasource.course.druid.username}")
    private String username;
    @Value("${spring.datasource.course.druid.password}")
    private String password;
    @Value("${spring.datasource.course.druid.driverClassName}")
    private String driverClassName;
    @Bean("courseDataSource")
    @Qualifier("courseDataSource")
    public DruidDataSource dataSource()
    {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(this.url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        System.out.println("course");
        return datasource;
    }
    @Bean("courseSqlSessionFactory")
    @Qualifier("courseDataSource")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("courseDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/courseMapper/*Mapper.xml"));
        return sessionFactory.getObject();
    }

    @Bean("courseTransactionManager")
    @Qualifier("courseDataSource")
    public DataSourceTransactionManager transactionManager(@Qualifier("courseDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("courseSqlSessionTemplate")
    @Qualifier("courseDataSource")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("courseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

这一部分为重中之重,所有的注解名称都需要更改(代码所有绿色部分)

  1. @MapperScan内的basePackages 是扫描MyBatis提供的mapper接口所在位置,sqlSessionTemplateRef 里面随意起名,对下面的注解没有影响,但是注意,要和其余几个配置类所起的名字要不同。
  2. @Value 这个是手动获取yml的配置信息,自动获取老出问题,我每次都获取不到。
  3. 细心的读者可能会发现DataSourceUser (第一个)类每个方法前面都有@Primary注解,而DataSourceCourse (第二个)类方法就变成了@Qualifier(这里面的名字也是随意,只要这几个类不同就行),这个是防止SpringBoot自动装配的时候,发现存在多个数据源,不知道该使用哪个而在启动时报错。 如有两个以上的数据源,就在其余的配置类的方法上和DataSourceCourse (第二个)一样使用@Qualifier注解。
  4. 剩下的Bean与作为参数的@Qualifier注解对应由读者自行观察就不再赘述。
  5. getResources方法参数是XML所在位置

3、而repository包与mapper包就不再赘述,但一定要注意与config包下类的对应关系

在这里感谢这位博主所写文章提供的思路

https://blog.csdn.net/weixin_36586564/article/details/105200968

你可能感兴趣的:(spring,boot,java,intellij-idea)