关于 hikari 多数据源配置的坑

来自姬鸿昌的知识库
Jihongchang讨论 | 贡献2023年2月17日 (五) 09:09的版本
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

application.yml

spring:
  datasource:
    hikari:
      datasource-world:
        jdbc-url: jdbc:mysql://127.0.0.1:3306/world
        username: root
        password: 123456
      datasource-testdb:
        jdbc-url: jdbc:mysql://127.0.0.1:3306/testdb
        username: root
        password: 123456

DataSourceTestdbConfig.java

package io.github.jihch.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "io.github.jihch.mapper.testdb", sqlSessionTemplateRef = "sqlSessionTemplateTestdb")
public class DataSourceTestdbConfig {

    @Bean("dataSourceTestdb")
    @ConfigurationProperties(prefix = "spring.datasource.hikari.datasource-testdb")
    public DataSource dataSourceTestdb() {
        return new HikariDataSource();
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryTestdb(@Qualifier("dataSourceTestdb") HikariDataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateTestdb(@Qualifier("sqlSessionFactoryTestdb") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

DataSourceWorldConfig.java

package io.github.jihch.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "io.github.jihch.mapper.world", sqlSessionTemplateRef = "sqlSessionTemplateWorld")
public class DataSourceWorldConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari.datasource-world")
    public DataSource dataSourceWorld() {
        return new HikariDataSource();
    }

    @Bean
    public SqlSessionFactory sqlSessionFactoryWorld(@Qualifier("dataSourceWorld") HikariDataSource dataSource)
            throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplateWorld(@Qualifier("sqlSessionFactoryWorld") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

这套多数据源配置在启动的时候一直在抛异常

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zaxxer.hikari.HikariDataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=dataSourceWorld)}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790) ~[spring-beans-5.3.13.jar:5.3.13]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346) ~[spring-beans-5.3.13.jar:5.3.13]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.13.jar:5.3.13]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.13.jar:5.3.13]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.13.jar:5.3.13]
	... 20 common frames omitted

定位半天发现容器里 type=javax.sql.DataSource 的对象两个都在 dataSourceTestdb 和 dataSourceWorld;

但是 type=HikariDataSource 的对象就只有 dataSourceTestdb 一个,dataSourceWorld 没有算在内;

试了试把注入到 SqlSessionFactory 的 Bean 定义方法的入参类型改成 javax.sql.DataSource 就没问题了。