当前位置: 首页 > 知识库问答 >
问题:

如何将Spring AbstractRoutingDataSource与动态数据源一起使用?

谭彦
2023-03-14

我在一个使用Spring、Spring数据JPA、Spring Security、Primefaces的项目中工作。。。

我正在学习关于spring动态数据源路由的教程。

在本教程中,您只能在预定义的数据源之间实现动态数据源切换。

以下是我的代码片段:

springContext jpa。xml

<bean id="dsCgWeb1" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName.Cargest_web}"></property>
    <property name="url" value="${jdbc.url.Cargest_web}"></property>
    <property name="username" value="${jdbc.username.Cargest_web}"></property>
    <property name="password" value="${jdbc.password.Cargest_web}"></property>
</bean>

<bean id="dsCgWeb2" class="org.apache.commons.dbcp.BasicDataSource">
    // same properties, different values ..
</bean>

<!--  Generic Datasource [Default : dsCargestWeb1]  -->
<bean id="dsCgWeb" class="com.cargest.custom.CargestRoutingDataSource">
    <property name="targetDataSources">
        <map>
            <entry key="1" value-ref="dsCgWeb1" />
            <entry key="2" value-ref="dsCgWeb2" />
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="dsCgWeb1" />
</bean>

我想做的是使targetDataSources映射与它的元素一样动态。

换句话说,我想获取一个特定的数据库表,使用存储在该表中的属性来创建我的数据源,然后把它们放在一个映射中,比如塔吉特数据源。

有办法做到这一点吗?

共有3个答案

贝浩歌
2023-03-14

它可以通过AbstractRoutingDataSource实现,并将信息保存在线程局部变量中。下面是一个很好的工作示例:多租户:使用Spring Data JPA管理多个数据源

易烨磊
2023-03-14

线程使用的数据源可能会不时更改。
应该注意并发,应用程序可能会在并发环境中出现并发问题。
线程绑定的AbstractRoutingDataSource示例

汝开畅
2023-03-14

AbstractRoutingDataSource中的任何内容都不会强制您使用数据源的静态映射。由您来构造一个实现Map的bean

我没有完整的示例代码。但这是我能想象的。在一个web应用程序中,每个客户机都有一个数据库,所有数据库都具有相同的结构——好吧,这将是一个奇怪的设计,比如说它只是一个示例。在登录时,应用程序为客户端创建数据源,并将其存储在sessionId索引的映射中——该映射是名为dataSources

@Autowired
@Qualifier("dataSources");
Map<String, DataSource> sources;

// I assume url, user and password have been found from connected user
// I use DriverManagerDataSource for the example because it is simple to setup
DataSource dataSource = new DriverManagerDataSource(url, user, password);
sources.put(request.getSession.getId(), dataSource);

您还需要一个会话侦听器来在其销毁方法中清理数据源

@Autowired
@Qualifier("dataSources");
Map<String, DataSource> sources;

public void sessionDestroyed(HttpSessionEvent se)  {
    // eventually cleanup the DataSource if appropriate (nothing to do for DriverManagerDataSource ...)
    sources.remove(se.getSession.getId());
}

路由数据源可能如下所示:

public class SessionRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();
        return request.getSession().getId();
    }

    @Autowired
    @Qualifier("dataSources")
    public void setDataSources(Map<String, DataSource> dataSources) {
        setTargetDataSources(dataSources);
}

我没有测试过任何东西,因为设置不同的数据库需要很多工作,但我觉得应该可以。在现实世界中,每个会话不会有不同的数据源,而是每个用户一个,每个用户有一个会话计数,但正如我所说,这是一个过于简化的示例。

 类似资料:
  • 问题内容: 我正在使用Spring,Spring Data JPA,Spring Security,Primefaces的项目中工作… 在本教程中,你只能在预定义的数据源之间实现动态数据源切换。 这是我的代码的片段: springContext-jpa.xml 我想做的就是使targetDataSources映射也与其元素一样动态。 换句话说,我想获取某个数据库表,使用存储在该表中的属性创建我的数

  • 我正在使用mat-table,并试图将MatTableDataSource与observable一起使用(我从web服务获取数据),但我不知道如何将MatTableDataSource配置为使用observable而不是数组。 这个问题的唯一解决方案是订阅ngOnInit方法中的observable并在新数据到达时始终创建新的MatTableDataSource吗?

  • 参考项目:在Apache Beam中观察与文件夹匹配的新文件 您可以将其用于简单的用例吗?我的用例是我让用户将数据上传到Cloud Storage- 我想做的是保持管道在流式模式下运行,一旦文件上传到Cloud Storage,它就会通过管道进行处理。watchfornewfile可以做到这一点吗? 我编写的代码如下: 没有任何内容被转发到Big Query,但管道显示它正在流式传输。

  • 问题内容: 在将应用程序从Struts 1迁移到Struts 2时 在某些地方,基于请求参数,同一操作类已用于不同类型的视图。 例如:如果is为1意味着需要附加一个参数,或者如果is 2意味着需要附加更多额外的参数,例如,我需要使用将动态参数传递给其他操作。 struts-config.xml 动作班 但是,我无法在Struts 2中做同样的事情。在Struts 2中,动态参数可以使用吗? 问题答

  • 我有一个使用Amplify(使用AppSync API和Cognito)制作的工作应用程序。我想制作另一个不同的应用程序,但与我的第一个项目共享一些数据(相同的产品,但不同的目标、用法和安全规则)。 有没有一种干净的方法可以在新项目中使用Amplify,告诉GraphQLAPI从我的第一个Amplify项目中获取DynamoDB中的一些数据? 这些数据会经常变化,而且会很重——所以我不太喜欢任何同