Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 动态更改Spring数据源_Java_Spring_Datasource - Fatal编程技术网

Java 动态更改Spring数据源

Java 动态更改Spring数据源,java,spring,datasource,Java,Spring,Datasource,我有一个Spring应用程序,我想动态更改数据源,即当输入DS URL时,Spring Bean和所有依赖项都会自动更新。我知道这有点奇怪,但无论如何我想实现这一点。 我的Spring配置如下: <bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource"> <property name="serverName" value="${jdbc.serverName}" /> &

我有一个Spring应用程序,我想动态更改数据源,即当输入DS URL时,Spring Bean和所有依赖项都会自动更新。我知道这有点奇怪,但无论如何我想实现这一点。 我的Spring配置如下:

<bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
    <property name="serverName" value="${jdbc.serverName}" />
    <property name="portNumber" value="${jdbc.portNumber}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="databaseName" value="${jdbc.databaseName}" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="majorDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="majorDataSource"/>
    <property name="configLocation" value="classpath:sqlmap-config.xml"/>
</bean>

问题是:

  • JDBCURL存储在属性中,这些属性可以在运行时更改

  • 一旦URL被更改,我需要重新创建数据源,可能还有依赖对象。我不知道如何在春天优雅地做这件事

  • 我知道Spring可以基于一个键动态地路由数据源,但数据源URL是在Spring中预定义的,不会在运行时更改。这不是我的情况。

    您可以通过扩展spring并重写应该返回引用要使用的数据源Springbean的键的方法
    determineCurrentLookupKey()
    ,来使用spring

    看看这个,它将向您展示一个如何使用该功能的示例

    基本上,为了回答您的问题,您需要做的是在XML配置中将这两个数据源定义为不同的Springbean。不需要动态创建一个,spring将同时加载两个,并根据
    determineCurrentLookupKey()
    方法中的条件动态使用一个或另一个

    这将导致以下情况:

    XML配置

    <!-- first data source -->
    <bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="${jdbc.major.serverName}" />
        <property name="portNumber" value="${jdbc.major.portNumber}" />
        <property name="user" value="${jdbc.major.username}" />
        <property name="password" value="${jdbc.major.password}" />
        <property name="databaseName" value="${jdbc.major.databaseName}" />
    </bean>
    <!-- second data source -->
    <bean id="minorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="${jdbc.minor.serverName}" />
        <property name="portNumber" value="${jdbc.minor.portNumber}" />
        <property name="user" value="${jdbc.minor.username}" />
        <property name="password" value="${jdbc.minor.password}" />
        <property name="databaseName" value="${jdbc.minor.databaseName}" />
    </bean>
    <!-- facade data source -->
    <bean id="dataSource" class="blog.datasource.CustomerRoutingDataSource">
       <property name="targetDataSources">
          <map>
             <entry key="MINOR" value-ref="minorDataSource"/>
             <entry key="MAJOR" value-ref="majorDataSource"/>
          </map>
       </property>
       <property name="defaultTargetDataSource" ref="majorDataSource"/>
    </bean>
    <!-- wiring up -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:sqlmap-config.xml"/>
    </bean>
    

    我不确定这样做是否正确,但你能做的就是这样

    <bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="dummydata" />
        <property name="portNumber" value="dummydata" />
        <property name="user" value="dummydata" />
        <property name="password" value="dummydata" />
        <property name="databaseName" value="dummydata" />
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="majorDataSource"/>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    

    请建议这种方法是否可行,因为我还是Spring新手

    我使用主数据库和次数据库进行故障切换。当主要数据库失败时,我会将次要数据库升级为主要数据库。然后我需要设置第三个备用数据库,它的URL将是动态的,在这里无法预定义。无论如何,我可能会强制对主数据库和次数据库使用静态IP,因此我不需要动态更改URL。您可以使用多租户策略。例如
    <bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="dummydata" />
        <property name="portNumber" value="dummydata" />
        <property name="user" value="dummydata" />
        <property name="password" value="dummydata" />
        <property name="databaseName" value="dummydata" />
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="majorDataSource"/>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    public class TestTransaction {
    
       @Autowired
       private DataSourceTransactionManager manager;
    
       private PlatformTransactionManager transactionManager;
    
       public testExecution(DataSource ds) {
           manager.setDataSource(ds);
           transactionManager = manager;
           TransactionDefinition def = new DefaultTransactionDefinition();
           TransactionStatus status = transactionManager.getTransaction(def);
           try {
               jdbcTemplate.update();
               transactionManager.commit(status);
           } catch (Exception ex) {
               transactionManager.rollback(status);
           }
       }
    }