spring多数据源实现

多数据源的动态调用是现在很多复杂系统都会出现的,spring提供了AbstractRoutingDataSource抽象类,可以实现动态数据库的调用。
查看这个类的代码getConnection()获取数据库连接,通过determineTargetDataSource()方法,这个方法实现通过了determineCurrentLookupKey()的抽象方法在子类实现,所以我们继承AbstractRoutingDataSource类,实现determineCurrentLookupKey()方法即可。
抽象类中的方法定义如下
protected DataSource determineTargetDataSource() {
		Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
		Object lookupKey = determineCurrentLookupKey();
		//要注意的是resolvedDataSources是个Map,所以应该在配置文件里初始化个map,其中key才是我们要在子方法里返回的值
		DataSource dataSource = this.resolvedDataSources.get(lookupKey);			
		if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
			dataSource = this.resolvedDefaultDataSource;
		}
		if (dataSource == null) {
			throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
		}
		return dataSource;
	}

代码如下新建DynamicDatasource类
public class DynamicDatasource extends AbstractRoutingDataSource {
	@Override
	protected Object determineCurrentLookupKey() {
		// TODO Auto-generated method stub
		String name = DBContextHandler.getDB();
		if(name == null){
			name = "mysql";	//默认mysql数据库
		}
		return name;
	}
}
创建辅助类DBContextHandler,通过ThreadLocal存储每个线程的唯一数据库名称
public class DBContextHandler {
	private static final ThreadLocal<String> tl = new ThreadLocal<String>();
	
	public static String getDB(){
		return tl.get();
	}
	
	public static void setDB(String dbName){
		tl.set(dbName);
	}
	
	public static void removeDB(){
		tl.remove();
	}
}

配置文件如下,同时可以控制事物
  	<bean id="mysqlDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  		<property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
  		<property name="username"><value>XXXX</value></property>
  		<property name="password"><value>XXXX</value></property>
  		<property name="url"><value>XXXX</value></property>
  	</bean>
  	
  	<bean id="oracleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
  		<property name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property>
  		<property name="username"><value>XXXX</value></property>
  		<property name="password"><value>XXXX</value></property>
  		<property name="url"><value>XXXX</value></property>
  	</bean>
  	
  	<bean id="dynamicDataSource" class="dynamic.datasource.DynamicDatasource">
  		<property name="targetDataSources">
  			<map>
  				<entry value-ref="mysqlDataSource" key="mysql"></entry>
  				<entry value-ref="oracleDataSource" key="oracle"></entry>
  			</map>
  		</property>
  	</bean>
  	
  	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  		<property name="dataSource" ref="dynamicDataSource"></property>
  	</bean>
  	
  	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  		<property name="dataSource" ref="dynamicDataSource"></property>
  	</bean>
  	
  	 <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">   
		 <property name="transactionManager" ref="transactionManager" />   
		 <property name="transactionAttributes">   
		 <props>   
		 <prop key="add">PROPAGATION_REQUIRED</prop>   
		 </props>   
		 </property>   
	 </bean>   
	   
	 <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">   
		 <property name="beanNames">   
			 <list>   
			 	<value>demoService</value>   
			 </list>   
		 </property>   
		 <property name="interceptorNames">   
			 <list>   
			 	<value>transactionInterceptor</value>   
			 </list>   
		 </property>   
	 </bean>  
  	<bean id="demoDao" class="dao.DemoDao">
  		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
  	</bean>
  	<bean id="demoService" class="service.DemoService">
  		<property name="demoDao" ref="demoDao"></property>
  	</bean>

猜你喜欢

转载自lpbj010.iteye.com/blog/2267154
今日推荐