AbstractRoutingDataSource不会更改连接 [英] AbstractRoutingDataSource doesn't change connection

查看:307
本文介绍了AbstractRoutingDataSource不会更改连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 AbstractRoutingDataSource 动态更改数据源,并使用 ThreadLocal 设置currentLookupKey。当每个http请求仅使用一个数据源时,它的效果很好。我使用 JpaRepository

I use AbstractRoutingDataSource to change data source dynamically and ThreadLocal to set up currentLookupKey. It works nice when I use only one data source per http request. I use 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控制器中获取数据时,

When I try to get data in my REST controller I get data only from one database.

REST控制器中的某些代码

Some code in my 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请求中仅获取一次数据源。

I tried to debug and it looks like Spring obtains data source only once in http request.

此方法仅调用一次。

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

有什么方法可以迫使Spring更改数据源。

Is there any way to force Spring to change data source.

推荐答案

您的问题可能与事务定界有关。

Your problem could be related with transaction delimitation.

当您定义 @Transactional 批注中,Spring会代表您创建开始和结束以及提交或回滚(如果需要)事务所需的所有东西。

When you define a @Transactional annotation in your code, Spring will create on your behalf all the stuff necessary to begin and end, and commiting or rollback if required, a transaction.

如您在doBegin 方法中看到的那样 DataSourceTransactionManager 的-jdbc / src / main / java / org / springframework / jdbc / datasource / DataSourceTransactionManager.java rel = nofollow noreferrer>源代码类-其他事务管理器也是如此-初始化事务时,Spring获得 Connection -这就是为什么方法 getConnection 仅被调用一次-,并且w不适用于该事务中针对数据库的所有基础操作之间的连接重用(对于ACID保留来说很有意义)。

As you can see in the doBegin method in the source code of the DataSourceTransactionManager class - the same applies to other transaction managers - , Spring obtains a Connection when the transaction is initialized - this is why the method getConnection is invoked only once - , and it will reuse that connection across all the underlying operations against the database within that transaction (it makes sense for ACID preservation).

因此,如果您需要在同一请求中连接到多个数据源在处理过程中,您可以在服务代码中定义不同的方法,每个方法都带有 @Transactional 批注,并在调用它们之前根据需要更改基础数据源:

So, if you need to connect to several data sources within the same request processing, you can define different methods in you service code, every one annotated with a @Transactional annotation, and change the underlying data source as you require before invoke them:

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

这篇关于AbstractRoutingDataSource不会更改连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆