将一个 DataSource 对象用于多个数据库连接 - 一次仅使用一个连接
Using one DataSource object for multiple DB connections - using only one connection at a time
我们能否只定义一个 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 class
@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 版本。谢谢!!
您可以定义一个 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 class:
public class DBRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDB();
}
}
和 DBContextHolder class:
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();
}
}
在您的服务中 class 在调用您的 DAO 之前,您设置了使路由数据源能够获得正确连接的密钥:
DBContextHolder.setDB("DB01");
try{
dao.executeQuery(sqlSentence);
}finally{
DBContextHolder.clearDB();
}
我们能否只定义一个 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 class
@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 版本。谢谢!!
您可以定义一个 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 class:
public class DBRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBContextHolder.getDB();
}
}
和 DBContextHolder class:
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();
}
}
在您的服务中 class 在调用您的 DAO 之前,您设置了使路由数据源能够获得正确连接的密钥:
DBContextHolder.setDB("DB01");
try{
dao.executeQuery(sqlSentence);
}finally{
DBContextHolder.clearDB();
}