如何在不重新启动应用程序的情况下使用新的数据库凭据连接数据库

How to use the new database credentials to connect with database without restarting the application

我有一个 Spring 应用程序,它使用 ComboPooledDataSource、LocalContainerEntityManagerFactoryBean 和 JpaTransactionManager 与数据库连接。该应用程序工作正常。以下是我的配置。

<!-- DataSource JavaConfig -->

@Configuration
public class DataSourceConfig
{
@Bean
public DataSource dataSource()
{
    try {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(getUsername());
        dataSource.setPassword(getPassword());
        dataSource.setDriverClass(driverClassName);
        dataSource.setJdbcUrl(jdbcUrl);
        dataSource.setMinPoolSize(minPoolSize);
        dataSource.setMaxPoolSize(maxPoolSize);
        dataSource.setCheckoutTimeout(checkoutTimeout);
        dataSource.setMaxIdleTime(maxIdleTime);
        dataSource.setIdleConnectionTestPeriod(idleConnectionTestPeriod);
        dataSource.setAcquireRetryAttempts(acquireRetryAttempts);
        dataSource.setAcquireRetryDelay(acquireRetryDelay);
        return dataSource;
    } catch (Exception ex) {
        LOGGER.error("Error occurred while initializing datasource ", ex);
    }
    return null;
  }
}

<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
    <property name="dataSource" ref="dataSource"/>
</bean>


<!-- Entity manager factory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="dbMigrationService">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitManager" ref="persistenceUnitManager"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="${hibernate.showSql}"/>
            <property name="databasePlatform" value="${hibernate.dialect}"/>
        </bean>
    </property>
    <property name="jpaProperties">
        <props>
            <!-- batch writing -->
            <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
            <prop key="hibernate.order_inserts">${hibernate.order_inserts}</prop>
            <prop key="hibernate.order_updates">${hibernate.order_updates}</prop>
            <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
        </props>
    </property>
</bean>

但是我的数据库密码经常使用 Hashicorp 保险库轮换,我有新密码。现在我需要使用新密码与数据库建立连接,我还需要在不重新启动应用程序的情况下执行此操作。那么是否可以在应用程序 运行 时更改数据源中使用的数据库凭据?如果是,我需要为此做什么?有人可以帮我弄这个吗?谢谢

我认为你需要做类似的事情。

public class DataSourceStateListener {
    @Autowired
    private DataSource dataSource;

    @EventListener
    public void changeDataSourceCredentials(DBCredentialsEvent event) {
        dataSource.setPassword(event.getPassword());
    } 
}

DBCredentialsEvent 应在从 Vault 请求新凭据时触发。

@Autowired
private ApplicationEventPublisher eventPublisher;

eventPublisher(new DBCredentialsEvent(vaultPassword));

我在 AbstractComboPooledDataSource 中找到了这些代码行。

public void setUser( String user ) {
    if ( diff( dmds.getUser(), user ) ) {
        dmds.setUser( user ); 
        this.resetPoolManager( false );
    }
}

public void setPassword( String password ) { 
    if ( diff( dmds.getPassword(), password ) ) {
        dmds.setPassword( password ); 
        this.resetPoolManager( false );
    }
}

因此,更改数据库用户或密码似乎也会重置池管理器。无论如何,应该在投入生产之前测试该行为。