Springboot整合多數(shù)據(jù)源代碼示例詳解
最近有個老項目想逐步將新業(yè)務(wù)的數(shù)據(jù)放到新的數(shù)據(jù)庫,以前的業(yè)務(wù)還得連接以前的數(shù)據(jù)庫,于是需要整合多數(shù)據(jù)源 。
多數(shù)據(jù)源實際上是繼承了AbstractRoutingDataSource類,這個類最終實現(xiàn)了DataSource接口,DataSource里只有一個getConnection方法,數(shù)據(jù)庫每次訪問的時候都要先通過這個方法獲取連接,所有多數(shù)據(jù)源就是每次訪問數(shù)據(jù)庫之前動態(tài)的改變數(shù)據(jù)源。
在請求前改變數(shù)據(jù)源當(dāng)然需要用到SpringAOP,自定義注解操作
項目結(jié)構(gòu)

下面上代碼:
首先是依賴:
<!--數(shù)據(jù)庫連接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--sqlserver-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
<!--數(shù)據(jù)庫連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency> <!--AOP-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
yml配置數(shù)據(jù)源
server:
port: 8888
spring:
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
datasource:
druid:
first:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
jdbc-url: jdbc:mysql://rm-uf6265pj340sc9447oo.mysql.rds.54565.com:3306/dm?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=utf-8
username: username
password: password
second:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc-url: jdbc:sqlserver://39.104.203.222:1433;DatabaseName=TestTLcom
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath*:/mapper/*Mapper.xml
type-aliases-package: com.zdyl.dynamicdatasourcedemo.entity
global-config:
#主鍵類型 0:"數(shù)據(jù)庫ID自增", 1:"用戶輸入ID",2:"全局唯一ID (數(shù)字類型唯一ID)", 3:"全局唯一ID UUID";
id-type: 3
#字段策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷"
field-strategy: 2
#駝峰下劃線轉(zhuǎn)換
db-column-underline: true
#刷新mapper 調(diào)試神器
refresh-mapper: true
#數(shù)據(jù)庫大寫下劃線轉(zhuǎn)換
#capital-mode: true
#序列接口實現(xiàn)類配置
#key-generator: com.baomidou.springboot.xxx
#邏輯刪除配置
#logic-delete-value: 0
#logic-not-delete-value: 1
#自定義填充策略接口實現(xiàn)
#meta-object-handler: com.baomidou.springboot.xxx
#自定義SQL注入器
#sql-injector: com.baomidou.springboot.xxx
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
定義數(shù)據(jù)庫名稱
/**
* 數(shù)據(jù)庫名稱
*/
public interface DataSourceNames {
String FIRST = "first";
String SECOND = "second";
}
動態(tài)數(shù)據(jù)源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 動態(tài)數(shù)據(jù)源
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(new HashMap<>(targetDataSources));
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static String getDataSource() {
return contextHolder.get();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static void clearDataSource() {
contextHolder.remove();
}
}
配置多數(shù)據(jù)源
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DataSourceNames;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DynamicDataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 多數(shù)據(jù)源配置
*/
@Configuration
@MapperScan("com.zdyl.dynamicdatasourcedemo.**.mapper*")
public class MybatisPluConfig {
/**
* 數(shù)據(jù)源配置
* @return
*/
@Bean
@ConfigurationProperties(prefix="spring.datasource.druid.first")
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix="spring.datasource.druid.second")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource){
Map<String, DataSource> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
return new DynamicDataSource(firstDataSource, targetDataSources);
}
/**
* mybatis-plus分頁插件<br>
* 文檔:http://mp.baomidou.com<br>
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
下面就是自定義注解
import java.lang.annotation.*;
/**
* 多數(shù)據(jù)源注解
* AOP攔截此注解更換數(shù)據(jù)源
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurDataSource {
String name() default "";
}
AOP
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DataSourceNames;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.DynamicDataSource;
import com.zdyl.dynamicdatasourcedemo.dynamicdatasource.annotation.CurDataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 多數(shù)據(jù)源,切面處理類
* AOP攔截多數(shù)據(jù)源注解 @CurDataSource 注解更換數(shù)據(jù)源
*/
@Slf4j
@Aspect
@Component
public class DataSourceAspect implements Ordered {
/**
* 切點
*/
@Pointcut("@annotation(com.zdyl.dynamicdatasourcedemo.dynamicdatasource.annotation.CurDataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
CurDataSource curDataSource = method.getAnnotation(CurDataSource.class);
if (curDataSource == null) {
DynamicDataSource.setDataSource(DataSourceNames.FIRST);
log.info("set datasource is " + DataSourceNames.FIRST);
} else {
DynamicDataSource.setDataSource(curDataSource.name());
log.info("set datasource is " + curDataSource.name());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
log.info("clean datasource");
}
}
@Override
public int getOrder() {
return 1;
}
}
最后主啟動了去掉數(shù)據(jù)源自動加載
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
最后我們來跑起來請求一下,測試一下是否正確
@RestController
public class CfgDeviceController {
@Resource
CfgDeviceService cfgDeviceService;
@Resource
CfgChargeStartInfoService cfgChargeStartInfoService;
@CurDataSource(name = DataSourceNames.FIRST)
@GetMapping("/test")
public void getUser() {
CfgDevice byId = cfgDeviceService.getById(19);
System.out.println(byId.toString());
}
@CurDataSource(name = DataSourceNames.SECOND)
@GetMapping("/test1")
public void getUser1() {
CfgChargeStartInfo byId = cfgChargeStartInfoService.getById(1);
System.out.println(byId.toString());
}
}

**如果不加注解,使用默認(rèn)數(shù)據(jù)源
至此就整合完了
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Springboot多數(shù)據(jù)源配置之整合dynamic-datasource方式
- SpringBoot整合Mybatis實現(xiàn)多數(shù)據(jù)源配置與跨數(shù)據(jù)源事務(wù)實例
- Springboot整合JPA配置多數(shù)據(jù)源流程詳解
- SpringBoot整合Mybatis Plus多數(shù)據(jù)源的實現(xiàn)示例
- SpringBoot+Mybatis plus實現(xiàn)多數(shù)據(jù)源整合的實踐
- SpringBoot使用Atomikos技術(shù)整合多數(shù)據(jù)源的實現(xiàn)
- SpringBoot2整合JTA組件實現(xiàn)多數(shù)據(jù)源事務(wù)管理
- Springboot整合多數(shù)據(jù)源配置流程詳細(xì)講解
相關(guān)文章
Java如何獲取數(shù)組和字符串的長度(length還是length())
這篇文章主要介紹了Java如何獲取數(shù)組和字符串的長度(length還是length()),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
詳談Java中Object類中的方法以及finalize函數(shù)作用
下面小編就為大家?guī)硪黄斦凧ava中Object類中的方法以及finalize函數(shù)作用。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
文件上傳SpringBoot后端MultipartFile參數(shù)報空問題的解決辦法
這篇文章主要介紹了文件上傳SpringBoot后端MultipartFile參數(shù)報空問題的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
SSH框架網(wǎng)上商城項目第5戰(zhàn)之商品類別級聯(lián)查詢和分頁功能
SSH框架網(wǎng)上商城項目第5戰(zhàn)之商品類別級聯(lián)查詢和分頁功能,寫一下CategoryServiceImpl實現(xiàn)類,完成數(shù)據(jù)庫的級聯(lián)查詢,感興趣的小伙伴們可以參考一下2016-05-05
Mybatis-plus+通用mapper(tk.mybatis)的使用
本文主要介紹了Mybatis-plus+通用mapper(tk.mybatis)的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧<BR>2024-03-03

