spring 管理多datasource
原文出处:http://blog.springsource.com/2007/01/23/dynamic-datasource-routing/
?
Spring 2.0.1 introduced an AbstractRoutingDataSource. I believe that it deserves attention, since (based on frequent questions from clients) I have a hunch that there are quite a few 'home-grown' solutions to this problem floating around. That combined with the fact that it is trivial to implement yet easy to overlook, and now I have several reasons to dust off my corner of the Interface21 team blog.
The general idea is that a routing DataSource acts as an intermediary – while the 'real' DataSource can be determined dynamically at runtime based upon a lookup key. One potential use-case is for ensuring transaction-specific isolation levels which are not supported by standard JTA. For that, Spring provides an implementation: IsolationLevelDataSourceRouter. Consult its JavaDoc for a detailed description including configuration examples. Another interesting use-case is determination of the DataSource based on some attribute of the current user's context. What follows is a rather contrived example to demonstrate this idea.
First, I created a Catalog that extends Spring 2.0's SimpleJdbcDaoSupport. That base class only requires an instance of any implementation of javax.sql.DataSource, and then it creates a SimpleJdbcTemplate for you. Since it extends JdbcDaoSupport, the JdbcTemplate is also available. However, the "simple" version provides many nice Java 5 conveniences. You can read more detail about that in this blog by Ben Hale.
Anyways, here's the code for my Catalog:
Catalog so that it can dynamically get connections from the 3 different databases at runtime based on the current customer's type. As I mentioned, the AbstractRoutingDataSource can be rather simple to implement. Here is my implementation:public
class
CatalogTests
extends
AbstractDependencyInjectionSpringContextTests {
02
?
?03
???
private
Catalog catalog;
04
?
?05
???
public
void
setCatalog(Catalog catalog) {
06
??????
this
.catalog = catalog;
07
???
}
08
?
?09
???
public
void
testDataSourceRouting() {
10
??????
CustomerContextHolder.setCustomerType(CustomerType.GOLD);
11
??????
List<Item> goldItems = catalog.getItems();
12
??????
assertEquals(
3
, goldItems.size());
13
??????
System.out.println(
"gold items: "
+ goldItems);
14
?
?15
??????
CustomerContextHolder.setCustomerType(CustomerType.SILVER);
16
??????
List<Item> silverItems = catalog.getItems();
17
??????
assertEquals(
2
, silverItems.size());
18
??????
System.out.println(
"silver items: "
+ silverItems);
19
?
?20
??????
CustomerContextHolder.clearCustomerType();
21
??????
List<Item> bronzeItems = catalog.getItems();
22
??????
assertEquals(
1
, bronzeItems.size());
23
??????
System.out.println(
"bronze items: "
+ bronzeItems);
24
???
}
25
?
?26
???
protected
String[] getConfigLocations() {
27
??????
return
new
String[] {
"/blog/datasource/beans.xml"
};
28
???
}
29
}
…and rather than simply taking a screenshot of the green bar, you'll notice I've provided some console output – the results!:
1
gold items: [gold item #
1
(
250.0
), gold item #
2
(
325.45
), gold item #
3
(
55.6
)]
2
silver items: [silver item #
1
(
25.0
), silver item #
2
(
15.3
)]
3
bronze items: [bronze item #
1
(
23.75
)]
?
As you can see, the configuration is simple. Better still, the data-access code is not concerned with looking up different DataSources. For more information, consult the JavaDoc for AbstractRoutingDataSource.