dynamic更改Spring数据源

我有一个Spring应用程序,我想dynamic地更改数据源,即。 当input一个DS URL时,Spring bean和所有的依赖关系会自动更新。我知道这有些奇怪,但无论如何,我想实现这一点。 我的Springconfiguration如下:

<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> 

问题是:

  1. JDBC URL存储在属性中,可以更改运行时。

  2. 一旦URL被更改,我需要重新创build数据源,也许依赖对象。 我不知道如何在spring优雅地做到这一点?

我知道Spring可以根据一个键dynamic地路由数据源,但是数据源URL是在Spring中预定义的,不会改变运行时。 这不是我的情况。

你可以使用Spring的AbstractRoutingDataSource来扩展它,并重写方法determineCurrentLookupKey() ,该方法应该返回引用数据源的spring bean的键。

看看spring source博客上的这篇博客文章 ,它将向您展示如何使用该function的示例。

基本上回答你的问题,你需要做的是在XMLconfiguration中将两个数据源定义为不同的spring bean。 没有必要dynamic地创build一个,Spring会加载这两个,并根据你的判断标准在这个方法中dynamic地使用一个或者另一个。

这将导致类似于:

XMLconfiguration

 <!-- 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> 

Java的

 public class MyRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // get the current url HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); if (request.getRequestURL().toString().endsWith("/minor")) return "MINOR"; else return "MAJOR"; } } 

我不确定这是否是正确的做法,但是你可以做的是这样的。

 <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"/> 

和Java类

 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); } } } 

请build议,如果这种方法可以工作,因为我还是spring新的