使用JPA时如何刷新DataSource bean?

问题描述 投票:0回答:1

我每隔 1 分钟就会刷新 Hikari 数据源。我正在使用 spring data JPA 来执行保存操作。但 JPA 指向旧的数据源 bean,我遇到了以下异常。

java.sql.SQLException: HikariDataSource HikariDataSource (hikariConnectionPool0) has been closed.
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:96)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:269)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:601)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:385)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:756)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at 

这用于关闭数据源。

((HikariDataSource) 数据源).close()

这用于创建新的数据源。

dataSource = new HikariDataSource(config);

spring jdbc spring-data-jpa datasource hikaricp
1个回答
0
投票

如果您的凭据每 1 分钟刷新一次,则不要使用 Spring Boot 自动配置的

DataSource
。这是一个
HikariDataSource
,是一个实际的连接池。关闭和刷新它不起作用,因为您无法重新设置已经存在的引用。另外,重新连接数据库也需要一段时间,其中密码可能已被重置。

而是使用

DriverManagerDataSource
并将其包裹在
UserCredentialsDataSourceAdapter
中。然后每分钟更新
username
中的
password
UserCredentialsDataSourceAdapter

@Bean
public DriverManagerDataSource driverManagerDataSource(DataSourceProperties props) {
  DriverManagerDataSource ds = new DriverManagerDataSource();
  ds.setUrl(props.getUrl());
  ds.setDriverClassName(props.determineDriverClassName());
  return ds;
}

@Bean
@Primary
public UserCredentialsDataSourceAdapter dataSource(DriverManagerDataSource ds) {
  UserCredentialsDataSourceAdapter dsa = new UserCredentialsDataSourceAdapter();
  dsa.setTargetDataSource(ds);
  return dsa;
}

通过此功能,您可以相应地设置

username
password
,当需要连接时,它将使用这些。

public class DataSourceUpdater {

  private final UserCredentialsDataSourceAdapter dsa;

  public DataSourceUpdater(UserCredentialsDataSourceAdapter dsa) {
    this.dsa=dsa;
  }

  public void doIt() {
    var username = //obtain new username
    var password = //obtain new password
    syncronized(dsa) {
      dsa.setUsername(username);
      dsa.setPassword(password);
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.