栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot配置多数据源

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot配置多数据源

SpringBoot配置多数据源总结 1.为何配置多数据源?

首先,当一个系统需要集成多个项目的时候,配置多数据源是不可避免的,比如在一个系统中,需要有主从库的配置(主库负责增删改,从库负责查询),或者当你的系统/服务需要对接多个系统,存入多个不同的表的时候,就需要配置多数据源。

P.S 也可以在服务中调用RPC通信去调用别的服务的方法去调用多数据源,但是这样有以下几个弊端:

(1)不同服务会有不同的git分支,当大家合作开发时,分支不同,而你的代码要去别人的服务里做修改,这样会导致一些版本和代码的冲突,不方便。

(2)当你的业务需要这个数据源做主要支持的时候,使用RPC会导致你频繁的去调用其他人的服务和其他项目的数据库,而且当其他人对这个数据源进行改动后,会对你的业务影响很大,这样的设计并不合理。

当然具体业务也需要具体分析,因地制宜,当无法避免配置多数据源时,要在SpringBoot/SpringCloud工程中配置多数据源

2.配置多数据源的思路

配置多数据源其实有很多种不同的方法,但是这些方法都大同小异,我在这里提供一个在我们项目中比较常见的一种配置多数据源的思路。

(1)application.yml/application.properties中,加入相应数据源的url/driverClass/username/password等信息,这里要说明一下,不同项目使用不同的数据库连接池,在我的例子中,使用的是阿里的Druid连接池

(2)配置多数据源时,要排除此项目/服务中不需要配置单数据源,所以在启动类注解SpringBootApplication上,使用exclude排除掉DataSourceAutoConfiguration这个类,此处一定要注意,如果不排除掉,数据源配置会是访问单数据源从而导致失败。

(3)配置不同数据源的Config类,这里每个项目使用的数据源个数也都是不同的,这里我们的demo提供的是一个双数据源的配置,所以我们有两个数据源配置类,这里要强调一下,数据源要有主从区别,主数据源一定要添加@Primary注解。具体的需要注意的点都写在注释了,所有数据信息均为测试数据信息,不包含机密信息~

e.g:

application.properties

# 从库
druid.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb1?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true
druid.datasource.username=root
druid.datasource.password=root

# 主库
druid.primarydb.url=jdbc:mysql://127.0.0.1:3306/testdb2?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true
druid.primarydb.username=root
druid.primarydb.password=root

DataApplication.java

@PropertySource(value = "classpath:common-${spring.profiles.active}.properties", encoding = "UTF-8")
@RestController
@Log4j2
// 这个注解一定要加上
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DataApplication {

    public static void main(String[] args) {
        SpringApplication.run(DataApplication.class, args);
        try {
            System.setProperty("hostName", InetAddress.getLocalHost().getHostName());
            Environment environment = ApplicationContextHolder.getBean(Environment.class);
            String prefix = environment.getProperty("redis.key.prefix");
            log.info("当前redis前缀:{}", prefix);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

RecruitmentDataSourceConfig

// Configuration声明是代码中的配置相关信息
@Configuration
// 扫包
@MapperScan(basePackages =
        "com.recruitment.infrastructure.mapper.generate.recruitment",
        sqlSessionTemplateRef = "recruitmentSqlSessionTemplate")
public class RecruitmentDataSourceConfig {

    
    @Bean
  	// 通过前缀去读相关数据库信息
    @ConfigurationProperties(prefix = "druid.primarydb")
    @Primary
    public DataSource recruitmentDataSource() {
        return new DruidDataSource();
    }

    
    @Bean
    @Primary
  	// 通过Qualifier注解,通过名称去加载对应的bean,这样在代码中不需要额外配置别的东西,直接注入所需要的mapper即可
    public SqlSessionFactory recruitmentSqlSessionFactory(
            @Qualifier("recruitmentDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setVfs(SpringBootVFS.class);
        // 配置configuration
        tk.mybatis.mapper.session.Configuration configuration = new tk.mybatis.mapper.session.Configuration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        // 会自动映射任意复杂的结果集(无论是否嵌套)
        configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
        // 采用驼峰式命名方法
        configuration.setMapUnderscoreToCamelCase(true);
        bean.setConfiguration(configuration);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(
                "classpath*:com/recruitment/infrastructure/mapper/config/recruitment
    @Bean
    @Primary
    public DataSourceTransactionManager recruitmentTransactionManager(
            @Qualifier("recruitmentDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    
    @Bean
    @Primary
    public SqlSessionTemplate recruitmentSqlSessionTemplate(
            @Qualifier("recruitmentSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

同理 从库配置与上面类似

DemandDataSourceConfig.java

@Configuration
@MapperScan(basePackages =
        "com.recruitment.infrastructure.mapper.generate.demand",
        sqlSessionTemplateRef = "demandSqlSessionTemplate")
public class DemandDataSourceConfig {

    
    @Bean
    @ConfigurationProperties(prefix = "druid.datasource")
    public DataSource demandDataSource() {
        return new DruidDataSource();
    }

    
    @Bean
    public SqlSessionFactory demandSqlSessionFactory(
            @Qualifier("demandDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
      	// VFS是文件虚拟化,这个看自己项目需不需要打开
        bean.setVfs(SpringBootVFS.class);
        // 配置configuration
        tk.mybatis.mapper.session.Configuration configuration = new tk.mybatis.mapper.session.Configuration();
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        // 会自动映射任意复杂的结果集(无论是否嵌套)
        configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
        // 采用驼峰式命名方法
        configuration.setMapUnderscoreToCamelCase(true);
        bean.setConfiguration(configuration);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(
                "classpath*:com/recruitment/infrastructure/mapper/config/demand
    @Bean
    public DataSourceTransactionManager demandTransactionManager(
            @Qualifier("demandDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    
    @Bean
    public SqlSessionTemplate demandSqlSessionTemplate(
            @Qualifier("demandSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

(4)修改对应Mapper的包名,在我的这个项目中,我在mapper.generate下新增了recruitment和demand两个文件夹,MapperScan通过扫描generate下不同的包名来区分不同的数据源

P.S 两个配置时遇到的Bug

(1)如果启动后业务逻辑代码提示Mybatis Invalid statement报错,那么请查看自己代码中有没有设置MapperLocation,单数据源中不需要设置MapperLocation,但是多数据源一定要set这个值。

(2)如果Application启动后提示有三个数据源的bean,而代码中只支持一个单例bean的时候,那么请在启动类上排除掉自动加载单数据源的类,也就是上文中所说的DataSourceAutoConfiguration这个类,如果测业务时只加载一个数据源的时候,也是这个原因。

(3)多说一句,一定要注意扫包时的包名路径,很重要,如果配置不对也是无法扫描到对应路径的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/331631.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号