最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mybatis多數(shù)據(jù)源動(dòng)態(tài)切換的完整步驟

 更新時(shí)間:2020年11月22日 09:45:15   作者:張教主  
這篇文章主要給大家介紹了關(guān)于mybatis多數(shù)據(jù)源動(dòng)態(tài)切換的完整步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

筆者主要從事c#開發(fā),近期因?yàn)轫?xiàng)目需要,搭建了一套spring-cloud微服務(wù)框架,集成了eureka服務(wù)注冊中心、
gateway網(wǎng)關(guān)過濾、admin服務(wù)監(jiān)控、auth授權(quán)體系驗(yàn)證,集成了redis、swagger、jwt、mybatis多數(shù)據(jù)源等各項(xiàng)功能。
具體搭建過程后續(xù)另寫播客介紹。具體結(jié)構(gòu)如下:

在搭建過程集成mybatis的時(shí)候,考慮到單一數(shù)據(jù)源無法滿足實(shí)際業(yè)務(wù)需要,故結(jié)合c#的開發(fā)經(jīng)驗(yàn),進(jìn)行多數(shù)據(jù)源動(dòng)態(tài)集成。

mybatis的多數(shù)據(jù)源可以采用兩種方式進(jìn)行,第一種是分包方式實(shí)現(xiàn),這種方式靈活性不高,而且較為繁瑣,故不做過多介紹。

另一種方式是采用AOP的思想,進(jìn)行注解動(dòng)態(tài)切換,參考網(wǎng)上教程,核心思想是依靠 繼承AbstractRoutingDataSource,重寫determineCurrentLookupKey()方法,在該方法中使用DatabaseContextHolder獲取當(dāng)前線程的dataSource。

但是網(wǎng)上方法大都是首先定義好各個(gè)datasource,比如有三個(gè)數(shù)據(jù)源,就需要實(shí)現(xiàn)定義好三個(gè)datasource,筆者感覺這種方法,在我目前這套框架中不夠靈活,因?yàn)楣P者采用的是微服務(wù)框架,考慮到各個(gè)服務(wù)都有可能使用不同的數(shù)據(jù)源,而多數(shù)據(jù)源動(dòng)態(tài)切換是放在公共方法中實(shí)現(xiàn)的,如果每有新的數(shù)據(jù)源就要定義一個(gè),對代碼的侵入性太高,在c#中,選擇數(shù)據(jù)源很容易,根據(jù)連接名稱就可以切換過去,如下所示:

<connectionStrings>
<add name="test1" connectionString="server=127.0.0.1;user id=root;password=123456;database=db1;charset=utf8" providerName="MySql.Data.MySqlClient" />
<add name="test2" connectionString="server=127.0.0.1;user id=root;password=123456;database=db2;charset=utf8" providerName="MySql.Data.MySqlClient" />
<add name="test3" connectionString="server=127.0.0.1;user id=root;password=123456;database=db3;charset=utf8" providerName="MySql.Data.MySqlClient" />
<connectionStrings>

能不能像c#這樣根據(jù)連接名稱就自動(dòng)選擇呢,筆者的連接配置如下所示:

spring:
 application:
 name: csg-auth
 datasource:
 kbase:
  - driverClassName: com.kbase.jdbc.Driver
  jdbcUrl: jdbc:kbase://127.0.0.1
  username: DBOWN
  password:
 jdbc:
  - driverClassName: com.mysql.cj.jdbc.Driver
  jdbcUrl: jdbc:mysql://localhost:3306/nacos?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false
  username: root
  password: 123456
  connName: nacos
  - driverClassName: com.mysql.cj.jdbc.Driver
  jdbcUrl: jdbc:mysql://localhost:3306/tpi?serverTimezone=GMT%2B8&useUnicode=false&characterEncoding=utf8&useSSL=false
  username: root
  password: 123456
  connName: tpi

其中kbase不用理會,是我們公司自己的數(shù)據(jù)庫,jdbc是維護(hù)的連接集合,其中connName就是我們自定義的連接名稱,
根據(jù)connName就可以自動(dòng)切換到對應(yīng)數(shù)據(jù)源。

筆者實(shí)現(xiàn)代碼如下:

第一步

首先,編寫DynamicDataSource類集成AbstractRoutingDataSource,重寫determineCurrentLookupKey方法,該方法主要作用是選擇數(shù)據(jù)源的key
代碼如下:

/**
 * 動(dòng)態(tài)數(shù)據(jù)源
 * */
public class DynamicDataSource extends AbstractRoutingDataSource {
 @Override
 protected Object determineCurrentLookupKey() {
  return DataSourceHolder.getDataSource();
 }
}

第二步

第二部編寫DataSourceHolder類,提供設(shè)置、獲取、情況數(shù)據(jù)源的方法,如下所示:

public class DataSourceHolder {
 /**
  * 線程本地環(huán)境
  */
 private static final ThreadLocal<String> dataSources = new ThreadLocal<String>();

 /**
  * 設(shè)置數(shù)據(jù)源
  */
 public static void setDataSources(String connName) {
  dataSources.set(connName);
 }

 /**
  * 獲取數(shù)據(jù)源
  */
 public static String getDataSource() {
  return dataSources.get();
 }

 /**
  * 清楚數(shù)據(jù)源
  */
 public static void clearDataSource() {
  dataSources.remove();
 }
}

第三步

第三步,編寫DataSourceConfig類,該類主要作用是讀取配置文件中的數(shù)據(jù)源連接集合,以及維護(hù)項(xiàng)目數(shù)據(jù)源的Bean對象,
代碼如下:

@Component
@ConfigurationProperties("spring.datasource")
public class DataSourceConfig {
 private List<DataSourceModel> jdbc;

 public Map<Object, Object> getDataSourceMap(){
  Map<Object, Object>map=new HashMap<>();
  if (jdbc!=null&&jdbc.size()>0){
   for (int i = 0; i < jdbc.size() ; i++) {
    DataSourceBuilder dataSourceBuilder=DataSourceBuilder.create();
    dataSourceBuilder.driverClassName(jdbc.get(i).getDriverClassName());
    dataSourceBuilder.password(jdbc.get(i).getPassword());
    dataSourceBuilder.username(jdbc.get(i).getUsername());
    dataSourceBuilder.url(jdbc.get(i).getJdbcUrl());
    map.put(jdbc.get(i).getConnName(),dataSourceBuilder.build());
   }
  }
  return map;
 }

 @Bean
 public DataSource csgDataSource(){
  DynamicDataSource dynamicDataSource=new DynamicDataSource();
  Map<Object,Object>dataSourceMap=getDataSourceMap();
  dynamicDataSource.setTargetDataSources(dataSourceMap);
   Object object= dataSourceMap.values().toArray()[0];
  dynamicDataSource.setDefaultTargetDataSource(object);
  return dynamicDataSource;
 }

 public void setJdbc(List<DataSourceModel> jdbc) {
  this.jdbc = jdbc;
 }

 public List<DataSourceModel> getJdbc(){
  return this.jdbc;
 }
}

其中,getDataSourceMap()方法,作用是根據(jù)配置的連接集合,生成AbstractRoutingDataSource所需要的resolvedDataSources。

而csgDataSource()方法,添加了@Bean注解,作用是讓mybatis的SqlSessionFactory,能夠使用咱們維護(hù)的數(shù)據(jù)源。

第四部

編寫MyBatisConfig類,該類主要作用是 配置好mybatis的數(shù)據(jù)源。

@Configuration
public class MyBatisConfig {

 @Autowired
 private DataSource csgDataSource;

 @Bean
 public SqlSessionFactory sqlSessionFactory() throws Exception {
  SqlSessionFactoryBean sqlSessionFactoryBean=new SqlSessionFactoryBean();
  sqlSessionFactoryBean.setDataSource(csgDataSource);
  sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
    .getResources("classpath:mapper/**/*.xml"));
  return sqlSessionFactoryBean.getObject();
 }

 @Bean
 public PlatformTransactionManager platformTransactionManager(){
  return new DataSourceTransactionManager(csgDataSource);
 }
}

可以看到,這里選擇的是我們定義好的csgDataSource,其作用也是如此。

第五步

編寫TargetDataSource注解

/**
 * 注解標(biāo)簽
 * 作用于 方法、接口、類、枚舉、注解
 * */

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface TargetDataSource {
 String connName();
}

其中connName,就是我們需要使用的數(shù)據(jù)源

第六步

編寫DataSourceExchange,改類為切面,作用于TargetDataSource注解,故使用TargetDataSource注解的時(shí)候,
會根據(jù)connName自動(dòng)選擇數(shù)據(jù)源。

@Aspect
@Component
public class DataSourceExchange {

 @Before("@annotation(TargetDataSource)")
 public void before(JoinPoint joinPoint){
  MethodSignature sign = (MethodSignature) joinPoint.getSignature();
  Method method = sign.getMethod();
  boolean isMethodAop= method.isAnnotationPresent(TargetDataSource.class);
  if (isMethodAop){
   TargetDataSource datasource = method.getAnnotation(TargetDataSource.class);
   DataSourceHolder.setDataSources(datasource.connName());
  }else {
   if (joinPoint.getTarget().getClass().isAnnotationPresent(TargetDataSource.class)){
    TargetDataSource datasource = joinPoint.getTarget().getClass().getAnnotation(TargetDataSource.class);
    DataSourceHolder.setDataSources(datasource.connName());
   }
  }
 }

 @After("@annotation(TargetDataSource)")
 public void after(){
  DataSourceHolder.clearDataSource();
 }
}

改切面作用于方法運(yùn)行前后,負(fù)責(zé)選擇、取消數(shù)據(jù)源。

第七部

開始驗(yàn)證,使用方法如下:

@Service
public class UserServiceImpl implements UserService {
 @Autowired
 private UserMapper userMapper;

 @Override
 @TargetDataSource(connName = "nacos")
 public List<UserEntity> getList() {
  List<UserEntity> list= userMapper.selectUserList();
  return list;
 }
}

在service中,在需要進(jìn)行數(shù)據(jù)庫操作的方法上,添加TargetDataSource注解,即可自動(dòng)切換到所需要的數(shù)據(jù)源。
至此,mybatis就可以動(dòng)態(tài)切換數(shù)據(jù)源了。

筆者從事java開發(fā)工作不多,改方法可能不是太好,也請各位看官勿噴~

總結(jié)

到此這篇關(guān)于mybatis多數(shù)據(jù)源動(dòng)態(tài)切換的文章就介紹到這了,更多相關(guān)mybatis多數(shù)據(jù)源動(dòng)態(tài)切換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot中如何通過main方法調(diào)用service或dao

    springboot中如何通過main方法調(diào)用service或dao

    這篇文章主要介紹了springboot中如何通過main方法調(diào)用service或dao,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java ShardingJDBC實(shí)戰(zhàn)演練

    Java ShardingJDBC實(shí)戰(zhàn)演練

    Sharding-JDBC 采用在 JDBC 協(xié)議層擴(kuò)展分庫分表,是一個(gè)以 jar 形式提供服務(wù)的輕量級組件,其核心思路是小而美地完成最核心的事情
    2021-11-11
  • java使用Jco連接SAP過程

    java使用Jco連接SAP過程

    這篇文章主要介紹了java使用Jco連接SAP過程,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java 三元操作符用法說明

    java 三元操作符用法說明

    這篇文章主要介紹了java 三元操作符用法說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 解決springboot+shiro 權(quán)限攔截失效的問題

    解決springboot+shiro 權(quán)限攔截失效的問題

    這篇文章主要介紹了解決springboot+shiro 權(quán)限攔截失效的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解feign調(diào)用session丟失解決方案

    詳解feign調(diào)用session丟失解決方案

    這篇文章主要介紹了詳解feign調(diào)用session丟失解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • IDEA生成javadoc的實(shí)現(xiàn)步驟

    IDEA生成javadoc的實(shí)現(xiàn)步驟

    Javadoc是一種用于生成API文檔的工具,它可以根據(jù)代碼中特定格式的注釋自動(dòng)生成文檔,本文主要介紹了IDEA生成javadoc的實(shí)現(xiàn)步驟,感興趣的可以了解一下
    2023-10-10
  • Java  Option用法詳解

    Java  Option用法詳解

    Optional類是Java8為了解決null值判斷問題,借鑒google guava類庫的Optional類而引入的一個(gè)同名Optional類,使用Optional類可以避免顯式的null值判斷,避免null導(dǎo)致的NPE,下面以一些典型場景為例,列出Optional API常用接口的用法,并附上相應(yīng)代碼,感興趣的朋友一起看看吧
    2024-01-01
  • IOC?容器啟動(dòng)和Bean實(shí)例化兩個(gè)階段詳解

    IOC?容器啟動(dòng)和Bean實(shí)例化兩個(gè)階段詳解

    這篇文章主要為大家介紹了IOC?容器啟動(dòng)和Bean實(shí)例化兩個(gè)階段詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • springboot 監(jiān)控管理模塊搭建的方法

    springboot 監(jiān)控管理模塊搭建的方法

    本篇文章主要介紹了springboot 監(jiān)控管理模塊搭建的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03

最新評論

信丰县| 玛曲县| 淮安市| 富裕县| 遵义县| 司法| 高平市| 禄丰县| 廉江市| 民丰县| 扬中市| 石首市| 色达县| 晋城| 辽宁省| 墨江| 花垣县| 隆德县| 岚皋县| 临漳县| 吉林市| 南通市| 嘉祥县| 井冈山市| 沙洋县| 丹棱县| 墨玉县| 白水县| 沧州市| 卓资县| 朝阳县| 公主岭市| 韶山市| 潜山县| 静宁县| 牟定县| 镇康县| 广饶县| 五大连池市| 读书| 宁明县|