springboot2+mybatis+druid多資料來源動態切換

springboot2+mybatis+druid多資料來源動態切換

springboot2+mybatis+druid多資料來源動態切換

多資料來源切換,首先需要例項化多個數據源DataSource,這裡以兩個資料來源為例,多個數據源類似。程式的處理單元是執行緒,所以我們藉助ThreadLocal動態設定當前執行緒的資料來源例項。最後我們需要寫一個AOP,攔截需要切換資料來源的方法,在攔截器裡實現資料來源修改。專案以springboot2結合druid,mysql,mybatis為例。

1。首先建立兩個資料庫,分別為first和second,簡單建立一張表各插入一條資料作為演示:

first資料庫,表t_user

springboot2+mybatis+druid多資料來源動態切換

second資料庫,表t_user

springboot2+mybatis+druid多資料來源動態切換

2。例項化兩個資料來源,簡單配置下資料來源相關屬性:

spring:

druid:

first:

driverClassName: com。mysql。cj。jdbc。Driver

url: jdbc:mysql://127。0。0。1:3306/first?charset=utf8mb4&useSSL=false

username: root

password: 123456

second:

url: jdbc:mysql://127。0。0。1:3306/second?charset=utf8mb4&useSSL=false

初始化動態資料來源,設定預設資料來源,根據key路由到對應資料來源

@Configuration

public class DruidDataSourceConfiguration {

@Bean(“firstDataSource”)

@ConfigurationProperties(“spring。druid。first”)

public DataSource firstDataSource(){

return DruidDataSourceBuilder。create()。build();

}

@Bean(“secondDataSource”)

@ConfigurationProperties(“spring。druid。second”)

public DataSource secondDataSource(){

@Bean

@Primary

public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {

DynamicDataSource dynamicDataSource = new DynamicDataSource();

dynamicDataSource。setDefaultTargetDataSource(firstDataSource);

Map targetDataSources = new HashMap<>(2);

targetDataSources。put(“first”,firstDataSource);

targetDataSources。put(“second”, secondDataSource);

dynamicDataSource。setTargetDataSources(targetDataSources);

return dynamicDataSource;

在ThreadLocal中設定執行緒持有的資料來源:

@Slf4j

public class DynamicDataSource extends AbstractRoutingDataSource {

private static final ThreadLocal contextHolder = new ThreadLocal<>();

public static void set(String name){

log。info(“set datasource:{}”, name);

contextHolder。set(name);

public static String get(){

return contextHolder。get();

public static void remove(){

log。info(“remove datasource:{}”, contextHolder。get());

contextHolder。remove();

@Override

protected Object determineCurrentLookupKey() {

log。info(“current datasource:{}”, DynamicDataSource。get());

return DynamicDataSource。get();

3。編寫自定義註解,需要切換資料來源的地方添加註解:

@Target(ElementType。METHOD)

@Retention(RetentionPolicy。RUNTIME)

public @interface MyDataSource {

String value() default “first”;

4。編寫AOP,處理自定義註解

@Aspect

@Component

public class DynamicDataSourceAspect {

@Pointcut(value=“@annotation(dataSource)”)

public void dataSourcePointCut(MyDataSource dataSource){}

@Before(value = “dataSourcePointCut(dataSource)”)

public void setDataSource(MyDataSource dataSource){

DynamicDataSource。set(dataSource。value());

@After(value = “dataSourcePointCut(dataSource)”)

public void removeDataSource(MyDataSource dataSource){

DynamicDataSource。remove();

5。測試,使用idea外掛EasyCode快速生成程式碼,參見小麥之前的文章

來吧,試試idea外掛EasyCode

@GetMapping(“{datasource}/{id}”)

public TUser selectOne(@PathVariable(“datasource”) String datatsource,@PathVariable(“id”) Integer id) {

if(“second”。equals(datatsource)){

return this。tUserService。queryByIdSecond(id);

return this。tUserService。queryById(id);

在service中新增一個自定義註解的方法:

public TUser queryById(Integer id) {

return this。tUserDao。queryById(id);

@MyDataSource(“second”)

public TUser queryByIdSecond(Integer id) {

6。驗證結果:

springboot2+mybatis+druid多資料來源動態切換

springboot2+mybatis+druid多資料來源動態切換

總結:

藉助抽象類AbstractRoutingDataSource可以根據key路由目標資料來源,在需要切換資料來源的地方手動標記,切換到對應的資料來源即可。