登录后进行Spring BootEntityManagerFactory初始化

时间:2019-02-05 09:24:14

标签: java spring-boot javafx

我用Spring Boot开发了一个JavaFX应用程序。此应用程序使用本地数据库(H2),但是数据库连接属性(如数据库名称,用户名,密码)由用户在登录屏幕上输入。

但是spring boot会初始化AppConfig.java中定义的所有bean,而我无法初始化javafx场景来显示UI。

将排除项放入@EnableAutoConfiguration注释无济于事。

@SpringBootApplication
@EnableAutoConfiguration(exclude= {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, HibernateJpaAutoConfiguration.class})   
public class MyApplication extends Application {

spring boot仍然尝试连接到数据库。

当然,一旦用户输入了数据库名称,用户名/密码,Spring Boot应该初始化与数据库相关的bean或以某种方式强制Spring Boot进行初始化,因为稍后它们是应用程序功能所必需的。

感谢任何提示!

4 个答案:

答案 0 :(得分:0)

您可以尝试在春季引导之前启动登录屏幕,然后将输入的值设置为系统属性。然后启动Spring Boot:

public static void main(String[] args) {
    // Start login screen

    // For all properties the user entered
    System.setProperty("spring.database.xy", "<value from UI>");

    SpringApplication.run(Application.class, args);
}

答案 1 :(得分:0)

您可以使用包装器提供自己的DataSource bean,该包装器仅在需要连接时才初始化数据源。

您的DataSource包装器可能会提供setUsername()setPassword(),供您尝试登录时使用。

我没有尝试过,但是请告诉我是否有问题。

public class AppDataSourceWrapper implements DataSource {

    private final DataSourceProperties dataSourceProperties;

    private String username;
    private String password;

    private DataSource dataSource;

    public AppDataSourceWrapper(DataSourceProperties dataSourceProperties) {
        this.dataSourceProperties = dataSourceProperties;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private DataSource getDataSource() {
        if (dataSource == null) {
            initDataSource();
        }

        return dataSource;
    }

    private void initDataSource() {
        this.dataSource = dataSourceProperties.initializeDataSourceBuilder()
                .username(username)
                .password(password)
                .build();
    }

    @Override
    public Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }

    // other override methods omitted for brevity

}

添加到您的配置中:

@Bean
public DataSource dataSource(DataSourceProperties dataSourceProperties) {
    return new AppDataSourceWrapper(dataSourceProperties);
}

根据用户访问请求,您可以执行以下操作:

AppDataSourceWrapper dsWrapper = (AppDataSourceWrapper) dataSource;
dsWrapper.setUsername(username);
dsWrapper.setPassword(password);

然后应在首次尝试连接时初始化数据源。

更新

Spring Boot JPA自动配置尝试在bean初始化期间(即JpaVendorAdapter中的JpaBaseConfiguration bean)连接到数据库,因此提供数据源包装器将无法完成工作。

可能的解决方案here

答案 2 :(得分:0)

听起来像您想要一种动态/惰性数据源bean。 您可以尝试通过创建自定义的RoutingDatasource实现来实现此目的,该实现扩展了 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource

如果需要一些示例,可以搜索SessionRoutingDataSource,DynamicRoutingDatasource或MultitenantDatasource。

您可以尝试在RoutingDatasource中使用某种NoopDatasource,以解决需要将数据源放在其中但用户尚未提供凭据的情况。

答案 3 :(得分:0)

我建议避免使用Spring Boot Starter JPA和数据源属性进行初始化。

保留数据源的属性,但将其命名为Spring Boot不需要的名称。然后,我将在登录时通过创建DataSource对象来初始化数据源。

另一种选择是定义一个dataSource bean并将其标记为惰性。