[英]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());
}
}
对于不同数据源的不同配置,我有多个像上面这样的类,我将它们添加到数据源 Bean 的可用 dbs static 列表中。
这是我的 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;
}
这是 db 上下文持有者,它可以进行设置默认数据库或获取当前数据库等操作:
@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 用户指南:
Spring 引导启用其基于脚本的数据库初始化程序的快速故障功能。 如果脚本导致异常,应用程序将无法启动。 您可以通过设置 spring.sql.init.continue-on-error 来调整该行为。
根据您的 spring 引导版本,该属性将被命名为
spring.sql.init.continue-on-error
或之前 Spring 启动 2.5
spring.datasource.continue-on-error
这太愚蠢了,但我通过在 application.properties 中添加以下内容解决了这个问题。
spring.jpa.database=sql_server
我不知道为什么我需要在属性文件中明确指定,但问题已经解决。 我会寻找它
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.