基本的なものは、AbstractRoutingDataSource
を使用して実現されています。
このクラスを継承し、抽象メソッドを実装します。
@Override
protected Object determineCurrentLookupKey() {
return name;
}
抽象メソッドは使用するデータソースの名前を返します。ここでは ThreadLocal を使用して現在使用中の名前を保存しています。
/**
* @author dengqn 2019/12/25-11:15
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
public static final ThreadLocal<String> context = new ThreadLocal<>();
public static final String MAIN_DATA_SOURCE = "mainDataSource";
public static final String DATA_SOURCE_240 = "dataSource240";
public static void setDataSource(String type) {
context.set(type);
}
public static String getDataSource() {
return context.get();
}
public static void clearDataSource() {
context.remove();
}
@Override
protected Object determineCurrentLookupKey() {
return context.get();
}
}
次に、複数のデータソースを設定し、それぞれのデータソースに異なる名前を持たせます。
<bean id="dataSource" class="com.boyasoftware.datasource.DynamicDataSource">
<property name="defaultTargetDataSource" ref="mainDataSource"/>
<property name="targetDataSources">
<map>
<entry key="mainDataSource" value-ref="mainDataSource"/>
<entry key="dataSource240" value-ref="dataSource240"/>
</map>
</property>
</bean>
注意すべきは、ThreadLocal が返す名前が見つからない場合、デフォルトのデータソースが使用されることです。
これで、このカスタムの可変データソースを使用することができます。スレッド間で切り替える際には互いに影響を与えません。
使用する際には、直接切り替えるだけです。
DynamicDataSource.clearDataSource();
DynamicDataSource.setDataSource(DynamicDataSource.DATA_SOURCE_240);
// 切り替えたいクエリのビジネスコード
DynamicDataSource.clearDataSource();
DynamicDataSource.setDataSource(DynamicDataSource.MAIN_DATA_SOURCE);