gpt4 book ai didi

java - AbstractRoutingDataSource 不会改变连接

转载 作者:行者123 更新时间:2023-12-01 12:07:01 27 4
gpt4 key购买 nike

我用 AbstractRoutingDataSource动态更改数据源和 ThreadLocal设置 currentLookupKey。当我每个 http 请求只使用一个数据源时,它工作得很好。我用 JpaRepository

@Component
@Primary
public class RoutingDataSource extends AbstractRoutingDataSource {

@Autowired
private DatabaseMap databaseMap;

@Override
public void afterPropertiesSet() {
setTargetDataSources(databaseMap.getSourcesMap());
setDefaultTargetDataSource(databaseMap.getSourcesMap().get("DEFAULT"));
super.afterPropertiesSet();
}

@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}

}

public class DatabaseContextHolder {

private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

public static void setDatabaseType(String string) {
contextHolder.set(string);
}

public static String getDatabaseType() {
return (String) contextHolder.get();
}

public static void clearDatabaseType() {
contextHolder.remove();
}
}

当我尝试在 REST Controller 中获取数据时,我只能从一个数据库中获取数据。

我的 REST Controller 中的一些代码
DatabaseContextHolder.setDatabaseType("db1");
//here I get data from db1 as expected
//I use JpaRepository
DatabaseContextHolder.clearDatabaseType();
DatabaseContextHolder.setDatabaseType("db2");
//here I should get data from db2 but get from db1

我尝试调试,看起来 Spring 在 http 请求中只获取一次数据源。

这个方法只调用一次。
@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}

有什么办法可以强制 Spring 更改数据源。

最佳答案

您的问题可能与交易定界有关。
当您定义 @Transactional 时在您的代码中添加注释,Spring 将代表您创建开始和结束所需的所有内容,并在需要时提交或回滚事务。
正如您在 doBegin 中看到的那样source code 中的方法的DataSourceTransactionManager class - 同样适用于其他事务管理器 - ,Spring 获得一个 Connection当事务初始化时 - 这就是方法 getConnection 的原因仅被调用一次 - ,并且它将在该事务中针对数据库的所有底层操作中重用该连接(这对于 ACID 保留是有意义的)。
所以,如果你需要在同一个请求处理中连接到多个数据源,你可以在你的服务代码中定义不同的方法,每个方法都用 @Transactional 注释。注释,并在调用它们之前根据需要更改基础数据源:

DatabaseContextHolder.setDatabaseType("db1");
// Invoke a service method annotated with @Transactional
// It can use the underlying JpaRepositories that you need
DatabaseContextHolder.clearDatabaseType();
DatabaseContextHolder.setDatabaseType("db2");
// Invoke again another (or the same, what you need) service method
// annotated with @Transactional, You should get data from db2 this time

关于java - AbstractRoutingDataSource 不会改变连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37561239/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com