1.aop+注解方式
在實際項目中很多時候會涉及到多個數據庫的訪問,或者數據庫讀寫分離的形式。
下面通過使用 Aspect+注解來實現mysql+oracle的多數據源配置(注意:事務一致性未提供)
首先要去oracle官網下載ojdbc的jar包,根據oracle的版本去下載,或者在下載的oracle的jdbc包下的lib里面有,然后導入項目中?。。?/strong>
動態(tài)數據源流程說明
Spring Boot 的動態(tài)數據源,本質上是把多個數據源存儲在一個 Map 中,當需要使用某個數據源時,從 Map 中獲取此數據源進行處理。而在 Spring 中,已提供了抽象類 AbstractRoutingDataSource 來實現此功能。因此,我們在實現動態(tài)數據源的,只需要繼承它,重寫determineCurrentLookupKey的方法即可
代碼如下:
1.數據庫連接信息配置
在application.yml中添加如下信息,根據自己項目的需要進行替換
spring:
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/數據庫名
username: root
password: root
slave:
type: com.alibaba.druid.pool.DruidDataSource
platform: oracle
jdbc-url: jdbc:oracle:thin:@localhost:1521:數據庫名
username: system
password: system
#指定數據源的全限定名
driver-class-name: oracle.jdbc.driver.OracleDriver
注意:根據springboot的版本不同,有不同的寫法,在springboot2.0的版本中,注意url要寫成jdbc-url,嘗試過url的話會報錯
2.數據源配置
根據連接信息,把數據源注入到 Spring 中,添加 DynamicDataSourceConfig
文件,配置如下
@Configuration
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
public class DynamicDataSourceConfig {
@Bean(DataSourceConstants.MASTER)
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(DataSourceConstants.SLAVE)
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@Primary
public DataSource dynamicDataSource() {
Map<Object, Object> dataSourceMap = new HashMap<>(2);
dataSourceMap.put(DataSourceConstants.MASTER, masterDataSource());
dataSourceMap.put(DataSourceConstants.SLAVE, slaveDataSource());
//設置動態(tài)數據源
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource());
return dynamicDataSource;
}
}
需要在 DynamicDataSourceConfig 中,排除 DataSourceAutoConfiguration 的自動配置,否則 會出現The dependencies of some of the beans in the application context form a cycle的錯誤
使用注解 Primary 優(yōu)先從動態(tài)數據源中獲取
DataSourceConstants
類:
public class DataSourceConstants {
public final static String MASTER = "master";
public final static String SLAVE = "slave";
}
3.動態(tài)數據源設置
添加動態(tài)數據源類
DynamicDataSource
和 DynamicDataSourceContextHolder
類
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getContextKey();
}
}
public class DynamicDataSourceContextHolder {
/*這是為了線程安全*/
private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>();
/* 設置/切換數據源*/
public static void setContextKey(String key) {
DATASOURCE_CONTEXT_KEY_HOLDER.set(key);
}
/* 獲取數據源名稱 */
public static String getContextKey() {
String key = DATASOURCE_CONTEXT_KEY_HOLDER.get();
return key == null ? DataSourceConstants.MASTER : key;
}
/*刪除當前數據源名稱*/
public static void removeContextKey() {
DATASOURCE_CONTEXT_KEY_HOLDER.remove();
}
}
4.使用AOP選擇數據源
自定義一個annotation?DbAnnotation
注解
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DbAnnotation {
/**
* 數據源名稱,默認master
*/
String value() default DataSourceConstants.MASTER;
}
定義數據源切面
@Aspect
@Component
public class DynamicDataSourceAspect {
//攔截DbAnnotation
@Pointcut("@within(com.example.constant.DbAnnotation)"+"||@annotation(com.example.constant.DbAnnotation)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
String dsKey = this.getDSAnnotation(joinPoint).value();
DynamicDataSourceContextHolder.setContextKey(dsKey);
try {
return joinPoint.proceed();
} catch (Exception ex) {
throw ex;
} finally {
DynamicDataSourceContextHolder.removeContextKey();
}
}
/**
* 根據類或方法獲取數據源注解
*/
private DbAnnotation getDSAnnotation(ProceedingJoinPoint joinPoint) {
//mybatis生成的代理類,所以獲取它的接口來獲取DbAnnotation注解信息
Class<?> targetClass = joinPoint.getTarget().getClass().getInterfaces()[0];
DbAnnotation dsAnnotation = targetClass.getAnnotation(DbAnnotation.class);
// 先判斷類的注解,再判斷方法注解
if (Objects.nonNull(dsAnnotation)) {
return dsAnnotation;
} else {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
DbAnnotation annotation = methodSignature.getMethod().getAnnotation(DbAnnotation.class);
return annotation;
}
}
}
在mapper接口上添加@DbAnnotation
注解,為slave數據源添加了個測試的mapper:
@Mapper
public interface OrUserMapper extends BaseMapper<OrUser> {
@Select("select *from tb_user")
@DbAnnotation(DataSourceConstants.SLAVE)
List<OrUser> select();
}
@RequestMapping("/user/select")
public void test(){
List<OrUser> select = orUserMapper.select();
System.out.println(select.get(0));
}
然后如果想要在同一個函數里面調用不同的數據庫的話,此時不能將注解定義在函數上面,不然mybatis-plus會報錯,因為mybatis-plus 默認來說是運行期間就只支持一種數據源,初始化的時候就已經決定了,無法動態(tài)轉換。
所以我們可以在一個方法里面需要調用不同數據庫的地方的函數或者mapper接口那邊定義使用的數據源即可
比如在mysql的mapper上面加上注解:
@Mapper
//可以加或者不加也可以
@DbAnnotation(DataSourceConstants.MASTER)
public interface UserMapper extends BaseMapper<User> {
}
其實加和不加都可以,因為不加的話使用的是默認的數據源, 默認的就是mysql
在使用oracle數據庫的mapper里面
@Mapper
public interface OrUserMapper extends BaseMapper<OrUser> {
@Select("select *from tb_user")
@DbAnnotation(DataSourceConstants.SLAVE)
List<OrUser> select();
}
測試:
public void select() {
List<OrUser> select = orUserMapper.select();
List<User> users = userMapper.selectList(null);
System.out.println(select.get(0));
System.out.println(users.get(0));
}
2.使用spring提供的一個依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
配置文件:
spring:
datasource:
dynamic:
primary: master # 配置默認數據庫
datasource:
#主庫數據源
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/數據庫名
username: root
password: root
slave:
type: com.alibaba.druid.pool.DruidDataSource
platform: oracle
url: jdbc:oracle:thin:@localhost:1521:數據庫名
username: system
password: system
#指定數據源的全限定名
driver-class-name: oracle.jdbc.driver.OracleDriver
然后在需要切換的地方使用@DS注解即可文章來源:http://www.zghlxwxcb.cn/news/detail-728627.html
@DS("slave")
public void test(){
List<OrUser> select = userMapper.select();
System.out.println(select.get(0).getUsername());
}
參考鏈接:springboot 配置多數據源(Aop+注解實現)_mj_940620的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-728627.html
到了這里,關于springboot+mybatis實現mysql和oracle多數據源的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!