spring dataSourceRouterが自動的にデータソースを切り替えます.
20612 ワード
spring多データソースの切り替えは主にAbstractRoutingDataSourceというルート類を使用しています.私達がカスタマイズしたルート配布類がAbstractRoutingDataSource類を継承した後、determinerentLook ukey()を書き直します.書き換えの内容は私達の配布規則です.この方法はspringがデータソースを選択する必要がある時に実行されます.その後、私達のカスタムルールに従って自動的に配信され、多データソースの切り替えが可能になります.
ステップは以下の通りです.
1、複数のデータソースを設定する
ここでトークンに格納されている文字列は、最も簡単な配布規則であり、対象の属性に応じて自動的に選択する必要がある場合は、トークンに対応するオブジェクトを記憶して、経路の中でIDなどの属性を取り出し、その後、私たちのルールに従って動的に戻ります.これは私達が自分で指定する必要がありません.
ステップは以下の通りです.
1、複数のデータソースを設定する
<!--
<bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="initialPoolSize" value="${c3p0.initialPoolSize}" />
<property name="minPoolSize" value="${c3p0.minPoolSize}" />
<property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
<property name="maxStatements" value="${c3p0.maxStatements}" />
<property name="checkoutTimeout" value="${c3p0.checkoutTimeout}" />
<property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
<property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
</bean>
-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.jdbcUrl}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="${druid.initialSize}" />
<property name="minIdle" value="${druid.minIdle}" />
<property name="maxActive" value="${druid.maxActive}" />
<property name="maxWait" value="${druid.maxWait}" />
<property name="timeBetweenEvictionRunsMillis" value="${druid.timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${druid.minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${druid.validationQuery}" />
<property name="testWhileIdle" value="${druid.testWhileIdle}" />
<property name="testOnBorrow" value="${druid.testOnBorrow}" />
<property name="testOnReturn" value="${druid.testOnReturn}" />
<property name="poolPreparedStatements" value="${druid.poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="${druid.maxPoolPreparedStatementPerConnectionSize}" />
<property name="filters" value="${druid.filters}" />
</bean>
<bean id="druidDataSource_1" parent="druidDataSource">
<property name="url" value="${jdbc.jdbcUrl1}" />
</bean>
2、ルータを配置して、このoddとevenに注意してください.彼は私達のデータソースの標識です.AbstractRoutingDataSourceルートdetermine Curent Lookukey()この方法の中でどれを返しますか?それに対応するデータソースです.「odd」を返すなら、druidDataSourceデータソースです.<bean id="dataSourcreRouter" class="cn.yyh.router.NMRoutingDataSource">
<property name="targetDataSources">
<map>
<entry key="odd" value-ref="druidDataSource" />
<entry key="even" value-ref="druidDataSource_1" />
</map>
</property>
<property name="defaultTargetDataSource" ref="druidDataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourcreRouter" />
</bean>
3、AbstractRoutingDataSourceルートの配布器を編纂して、このNMRoutingTokenは何のラクトですか?このNMRoutingTokenは、ThreadLocalに記憶されているトークンの一つです.ThreadLocalは、現在のスレッド内のmapオブジェクトです.public class NMRoutingDataSource extends AbstractRoutingDataSource {
protected Object determineCurrentLookupKey() {
NMRoutingToken token = NMRoutingToken.getCurrentToken();
if (token != null) {
String dataSourceName = token.getDataSourceName();
//
NMRoutingToken.unbindToken();
return dataSourceName;
}
return null;
}
}
4、見えますが、実はNMRoutingTokenは現在のスレッドの中にあるThreadLocalに文字列を格納しています.前にdetermine Currennt Lookukeyと言いました.何に戻りますか?springは自動的にそのデータソースを選択します.それなら、私達new NMRoutingToken(「odd」)は彼をThreadLocalに結びつけて、determine Current Lookukey()で取り出せばいいです.public class NMRoutingToken {
private static ThreadLocal<NMRoutingToken> token = new ThreadLocal<NMRoutingToken>();
private String dataSourceName;
public String getDataSourceName() {
return dataSourceName;
}
public NMRoutingToken(String dataSourceName) {
super();
this.dataSourceName = dataSourceName;
bindToken(this);
}
/**
*
*/
private static void bindToken(NMRoutingToken t) {
token.set(t);
}
/**
*
*/
public static void unbindToken() {
token.remove();
}
/**
*
*/
public static NMRoutingToken getCurrentToken() {
return token.get();
}
}
5、テストpublic class NMDataSourceTest extends BaseTest {
@Autowired
private UserMapper userMapper;
@Autowired
private IUserService userService;
@Test
/**
*
*/
public void testMapper() {
/**
* ,
*/
int count1 = userMapper.getCount();
System.out.println(count1);
/**
* odd
*/
NMRoutingToken token = new NMRoutingToken("odd");
count1 = userMapper.getCount();
System.out.println(count1);
/**
* even
*/
token = new NMRoutingToken("even");
count1 = userMapper.getCount();
System.out.println(count1);
/**
*
*/
token = new NMRoutingToken("asdf");
count1 = userMapper.getCount();
System.out.println(count1);
}
@Test
/**
*
* , tomcat , , ,
* , NMRoutingDataSource determineCurrentLookupKey() ,
* ,
*/
public void testService() {
userService.getNMCount();
}
}
@Transactional(readOnly = true)
public void getNMCount() {
int count1 = -1;
/**
* even
*/
new NMRoutingToken("even");
count1 = userMapper.getCount();
System.out.println(count1);
/**
* odd , even
*/
new NMRoutingToken("odd");
count1 = userMapper.getCount();
System.out.println(count1);
}
実例ダウンロード:サンプルのダウンロードここでトークンに格納されている文字列は、最も簡単な配布規則であり、対象の属性に応じて自動的に選択する必要がある場合は、トークンに対応するオブジェクトを記憶して、経路の中でIDなどの属性を取り出し、その後、私たちのルールに従って動的に戻ります.これは私達が自分で指定する必要がありません.
:tomcat , service 。
service 。
:
@Tranctional
AService(){
methodA(){
dataSourceA.insert();
dataSourceB.update();
}
}
AService(){
@Tranctional
methodA(){
dataSourceA.insert();
dataSourceB.update();
}
}
( , ) , src/test/java/ResourceTest.java
:
Service(){
aService.insert();
bService.update();
}
AService{
@Tranctional
insert();
}
BService{
@Tranctional
update();
}