将一个DataSource对象用于多个数据库连接 - 一次只使用一个连接

时间:2015-02-08 18:15:03

标签: spring spring-jdbc spring-4

我们是否可以只定义一个DataSource对象并在连接到不同数据库的运行时动态连接它?我需要一次只连接一个数据库。

我将传递数据库的名称作为参数。我将从属性文件中查找数据库URL和其他详细信息,然后我需要使用数据库URL连接到数据库。

简而言之 - 我不知道我需要连接的数据库的数量。我将按照某种语法(如前缀DB01等)在 database.properties 文件中配置所有可能的数据库连接详细信息。数据库的名称将作为参数传递,我需要对该数据库执行查询。

database.properties 文件

DB01.driver=com.ibm.db2.jcc.DB2Driver
DB01.url=jdbc:db2://localhost:50000/SAMPLE
DB01.username=db2admin
DB01.password=db2admin

DAO

    @Autowired
    @Qualifier("DB01") // how do I make this dynamic ?
    private DataSource   datasource;
    private JdbcTemplate jdbcTemplate;

    // some more code

    public SqlRowSet executeQuery(String sqlQuery)
    {
        // can I pass the DB name here (the database.properties file will have the DB details 
        // with this name as given above) and set the DataSource Object accordingly ?
        // so that the query will be executed against that DB ?
        setJdbcTemplate(new JdbcTemplate(this.datasource));
        return getJdbcTemplate().queryForRowSet(sqlQuery);
    }

使用Spring v4.1.4 RELEASE。谢谢!!

1 个答案:

答案 0 :(得分:1)

您可以定义一个Routing DataSource,它根据一个键将getConnection方法重定向到一个或另一个数据源,在您的情况下,它似乎是数据库名称。

例如,spring xml:

     ....
    <bean id="DB01DataSource" parent="parentDatasource" p:url="${DB01.url}" ... />
    <bean id="DB02DataSource" parent="parentDatasource" p:url="${DB02.url}" .../>

    <bean id="dataSource" class="DBRoutingDataSource">
    <property name="targetDataSources">
       <map key-type="java.lang.String">
          <entry key="DB01" value-ref="DB01DataSource"/>
          <entry key="DB02" value-ref="DB02DataSource"/>
       </map>
    </property>
    <property name="defaultTargetDataSource" ref="DB01DataSource"/>
    </bean>
     ....

DBRoutingDataSource类:

public class DBRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DBContextHolder.getDB();
    }
}

和DBContextHolder类:

    public final class DBContextHolder {

        private static final ThreadLocal<String>    CONTEXT = new ThreadLocal<String>();

        private DBContextHolder() {
            // empty
        }

        public static void setDB(final String db) {
            CONTEXT.set(db);
        }

        public static String getDB() {
            return CONTEXT.get();
        }

        public static void clearDB() {
            CONTEXT.remove();
        }
    }

在调用DAO之前,在服务类中设置密钥,使路由数据源能够获得正确的连接:

 DBContextHolder.setDB("DB01");
 try{
   dao.executeQuery(sqlSentence);
 }finally{
   DBContextHolder.clearDB();
 }