Spring 如何在运行时创建数据源 bean 而不会导致应用程序崩溃?

How to create datasource bean at runtime without crashing app in Spring?

我正在连接到多个数据源,但有时某些数据源可能处于脱机状态,那时我在应用程序上遇到错误并且应用程序在启动时失败。

我想在启动时跳过数据源配置...我尝试了几种方法通过添加

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration 

到application.properties,我也试过添加

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})

到主 class 但它仍然尝试配置数据源。

我还尝试在所有方法和构造函数上使用 @Lazy 注释,如下所示,但在创建 fooEntityManagerFactory 时仍然出现错误

@Lazy
@Configuration
@EnableJpaRepositories(basePackages = "com.heyo.tayo.repository.foo", entityManagerFactoryRef = "fooEntityManagerFactory", transactionManagerRef = "fooTransactionManager")
public class PersistencefooConfiguration {

    @Autowired
    private DbContextHolder dbContextHolder;

    @Lazy
    @Bean
    @ConfigurationProperties("tay.datasource.foo")
    public DataSourceProperties fooDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Lazy
    @Bean
    @ConfigurationProperties("tay.datasource.foo.configuration")
    public DataSource fooDataSource() {
        DataSource dataSource = fooDataSourceProperties().initializeDataSourceBuilder()
                    .type(BasicDataSource.class).build();
        dbContextHolder.addNewAvailableDbType(DbTypeEnum.foo);

        return dataSource;
    }

    @Lazy
    @Bean(name = "fooEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean fooEntityManagerFactory(
            EntityManagerFactoryBuilder builder) {

//THE CODE IS FAILING AT BELOW RETURN CASE

        return builder
                .dataSource(fooDataSource())
                .packages("com.heyo.tayo.model.foo")
                .build();
    }

    @Lazy
    @Bean
    public PlatformTransactionManager fooTransactionManager(
            final @Qualifier("fooEntityManagerFactory") LocalContainerEntityManagerFactoryBean fooEntityManagerFactory) {
        return new JpaTransactionManager(fooEntityManagerFactory.getObject());
    }

}

对于不同数据源的不同配置,我有多个像上面那样的 classes,我正在将它们添加到数据源 Bean 的可用 dbs 静态列表中。

这是我的 dbadapter 工厂 class。

这是我创建相应数据库适配器的 dbAdaptor 工厂

@Service
public class DbAdapterFactory {

    @Autowired
    private BeanFactory beanFactory;

    @Autowired
    private DbContextHolder dbContextHolder;

    public DBAdapter dbAdapter(){

        DbTypeEnum currentDb = dbContextHolder.getCurrentDb();
        DBAdapter dbAdapter = null;

        if(currentDb == DbTypeEnum.FOODB) {
            dbAdapter = beanFactory.getBean(foodbadaptor.class);
        } else {
            dbAdapter = beanFactory.getBean(koodbadaptor.class);
        }

        return dbAdapter;
    }

这是数据库上下文持有者,它可以进行设置默认数据库或获取当前数据库等操作:

@Component
public class DbContextHolder {

    private DbTypeEnum dbType = DbTypeEnum.FOODB;
    private Set<DbTypeEnum> availableDbTypes = new HashSet<>();

    public void setCurrentDb(DbTypeEnum dbType) {
        this.dbType = dbType;
    }

    public DbTypeEnum getCurrentDb() {
        return this.dbType;
    }

    public List<DbTypeEnum> getAvailableDbTypes() {
        return new ArrayList<>(availableDbTypes);
    }

    public void addNewAvailableDbType(DbTypeEnum dbTypeEnum) {
        availableDbTypes.add(dbTypeEnum);
    }
}

我做了所有的@Lazy 或尝试了 @SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) 但仍然有东西在调用以创建 bean 并出现错误并且应用程序正在关闭。我想在 try-catch 块中使用该配置和数据源,并且不要在运行时停止应用程序。我怎样才能做到这一点,或者我在该配置或注释中缺少什么?

我相信您可以简单地添加到您的应用程序属性中

spring.sql.init.continue-on-error=true

根据 Spring Boot 2.5.5 用户指南:

https://docs.spring.io/spring-boot/docs/2.5.5/reference/htmlsingle/#howto-initialize-a-database-using-spring-jdbc

Spring Boot 启用其基于脚本的数据库初始化程序的快速失败功能。如果脚本导致异常,应用程序将无法启动。您可以通过设置 spring.sql.init.continue-on-error.

来调整该行为

根据您的 spring 引导版本,属性 将被命名为

spring.sql.init.continue-on-error

或 Spring Boot 2.5

之前
spring.datasource.continue-on-error

这太愚蠢了,但我通过在 application.properties.

中添加以下内容解决了这个问题
spring.jpa.database=sql_server

我不知道为什么我需要在属性文件中明确指定,但问题已解决。我去找找