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 用户指南:
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
我不知道为什么我需要在属性文件中明确指定,但问题已解决。我去找找
我正在连接到多个数据源,但有时某些数据源可能处于脱机状态,那时我在应用程序上遇到错误并且应用程序在启动时失败。
我想在启动时跳过数据源配置...我尝试了几种方法通过添加
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 用户指南:
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
我不知道为什么我需要在属性文件中明确指定,但问题已解决。我去找找