繼續上篇文章如何使用mybatis3+spring3而且配置多數據源呢
先上代碼在講解吧
替換上一篇中spring中datasource的配置
Java代碼
- <!-- 數據源配置 -->
- <bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <property name="driverClassName" value="com.mysql.jdbc.Driver" />
- <property name="url"
- value="jdbc:mysql://localhost:3306/payoffdatabase?useUnicode=true&characterEncoding=UTF-8" />
- <property name="username" value="root" />
- <property name="password" value="root" />
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
-
- <bean id="ds2" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <property name="driverClassName" value="com.mysql.jdbc.Driver" />
- <property name="url"
- value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />
- <property name="username" value="root" />
- <property name="password" value="root" />
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
-
-
- <bean id="dataSource" class="a.b.router.DynamicDataSource">
- <property name="targetDataSources">
- <map key-type="java.lang.String">
- <entry value-ref="ds1" key="ds1"></entry>
- <entry value-ref="ds2" key="ds2"></entry>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="ds1"></property>
- </bean>
新的類DynamicDataSource
Java代碼
- package a.b.router;
-
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
-
- public class DynamicDataSource extends AbstractRoutingDataSource {
- @Override
- protected Object determineCurrentLookupKey() {
- return DataSourceContextHolder.getDbType();
- }
- }
新的類DataSourceContextHolder
Java代碼
- package a.b.router;
-
- public class DataSourceContextHolder {
-
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
-
- public static void setDbType(String dbType) {
- contextHolder.set(dbType);
- }
-
- public static String getDbType() {
- return ((String) contextHolder.get());
- }
-
- public static void clearDbType() {
- contextHolder.remove();
- }
- }
原來的單元測試新添加一行信息,修改成
Java代碼
- @Test
- public void addTest() throws Exception {
- UserLogin userLogin = new UserLogin();
- userLogin.setPassword("102");
- userLogin.setUsername("102");
- DataSourceContextHolder.setDbType("ds2");
-
- service.add(userLogin);
- }
最主要的變化是DynamicDataSource 類,這個類繼承了AbstractRoutingDataSource,咱們再繼續考察,發現這個類實現了datasource這個接口。
再仔細研究,發現我配置了多個數據源給DynamicDataSource,默認的數據源是ds1。
咱們研究下AbstractRoutingDataSource類的代碼,主要是兩個實現datasource的方法
Java代碼
- public Connection getConnection() throws SQLException {
- return determineTargetDataSource().getConnection();
- }
-
- public Connection getConnection(String username, String password) throws SQLException {
- return determineTargetDataSource().getConnection(username, password);
- }
根據這段代碼發現主要玄機都在determineTargetDataSource()方法上。
Java代碼
- protected DataSource determineTargetDataSource() {
- Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
- Object lookupKey = determineCurrentLookupKey();
- 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;
- }
根據這段代碼發現,首先在使用數據源以前,首先判斷使用數據源的key,也就是咱們配置給
Java代碼
- private Map<Object, Object> targetDataSources;
這個map中的key值,找到key值以後再找到對應的datasource而後並使用這個數據源。 從上面咱們發現,實際上DynamicDataSource只是在內部封裝了數據源,而後調用它,只不過在內部他加了一些控制而已。(此處不知道是否能夠理解爲代理模式) 再深一步想一想,此處使用的orm層是mybatis,若是換成hibernate呢,或者jdbctemplate呢。 實際上這個方法都適用。