日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解SpringBoot+Mybatis實現動態數據源切換

瀏覽:124日期:2023-03-12 18:32:54
業務背景

電商訂單項目分正向和逆向兩個部分:其中正向數據庫記錄了訂單的基本信息,包括訂單基本信息、訂單商品信息、優惠卷信息、發票信息、賬期信息、結算信息、訂單備注信息、收貨人信息等;逆向數據庫主要包含了商品的退貨信息和維修信息。數據量超過500萬行就要考慮分庫分表和讀寫分離,那么我們在正向操作和逆向操作的時候,就需要動態的切換到相應的數據庫,進行相關的操作。

解決思路

現在項目的結構設計基本上是基于MVC的,那么數據庫的操作集中在dao層完成,主要業務邏輯在service層處理,controller層處理請求。假設在執行dao層代碼之前能夠將數據源(DataSource)換成我們想要執行操作的數據源,那么這個問題就解決了

環境準備:

1.實體類

@Datapublic class Product {private Integer id;private String name;private Double price;}

2.ProductMapper

public interface ProductMapper { @Select('select * from product') public List<Product> findAllProductM(); @Select('select * from product') public List<Product> findAllProductS(); }

3.ProductService

@Service public class ProductService { @Autowired private ProductMapper productMapper; public void findAllProductM(){ // 查詢Master List<Product> allProductM = productMapper.findAllProductM(); System.out.println(allProductM); } public void findAllProductS(){ // 查詢Slave List<Product> allProductS = productMapper.findAllProductS(); System.out.println(allProductS); } }具體實現

第一步:配置多數據源

首先,我們在application.properties中配置兩個數據源

spring.druid.datasource.master.password=root spring.druid.datasource.master.username=root spring.druid.datasource.master.jdbc- url=jdbc:mysql://localhost:3306/product_master? useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC spring.druid.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver spring.druid.datasource.slave.password=root spring.druid.datasource.slave.username=root spring.druid.datasource.slave.jdbc- url=jdbc:mysql://localhost:3306/product_slave? useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC spring.druid.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver在SpringBoot的配置代碼中,我們初始化兩個數據源:@Configuration public class MyDataSourceConfiguratioin { Logger logger = LoggerFactory.getLogger(MyDataSourceConfiguratioin.class); /*** Master data source. */ @Bean('masterDataSource') @ConfigurationProperties(prefix = 'spring.druid.datasource.master') DataSource masterDataSource() { logger.info('create master datasource...'); return DataSourceBuilder.create().build(); } /*** Slave data source. */ @Bean('slaveDataSource') @ConfigurationProperties(prefix = 'spring.druid.datasource.slave') DataSource slaveDataSource() { logger.info('create slave datasource...'); return DataSourceBuilder.create().build(); } @Bean @Primary DataSource primaryDataSource(@Autowired @Qualifier('masterDataSource')DataSource masterDataSource, @Autowired @Qualifier('masterDataSource')DataSource slaveDataSource){logger.info('create routing datasource...'); Map<Object, Object> map = new HashMap<>(); map.put('masterDataSource', masterDataSource); map.put('slaveDataSource', slaveDataSource); RoutingDataSource routing = new RoutingDataSource(); routing.setTargetDataSources(map); routing.setDefaultTargetDataSource(masterDataSource); return routing; }}

第二步:編寫RoutingDataSource然后,我們用Spring內置的RoutingDataSource,把兩個真實的數據源代理為一個動態數據源:

public class RoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return RoutingDataSourceContext.getDataSourceRoutingKey(); } }

第三步:編寫RoutingDataSourceContext用于存儲當前需要切換為哪個數據源

public class RoutingDataSourceContext { // holds data source key in thread local: static final ThreadLocal<String> threadLocalDataSourceKey = new ThreadLocal<>(); public static String getDataSourceRoutingKey() { String key = threadLocalDataSourceKey.get(); return key == null ? 'masterDataSource' : key; } public RoutingDataSourceContext(String key) { threadLocalDataSourceKey.set(key); } public void close() { threadLocalDataSourceKey.remove(); }}

測試(一下代碼為controller中代碼)

@GetMapping('/findAllProductM')public String findAllProductM() {String key = 'masterDataSource';RoutingDataSourceContext routingDataSourceContext = new RoutingDataSourceContext(key);productService.findAllProductM();return 'master';}@GetMapping('/findAllProductS')public String findAllProductS() {String key = 'slaveDataSource'; RoutingDataSourceContext routingDataSourceContext = new RoutingDataSourceContext(key); productService.findAllProductS(); return 'slave';}

以上代碼即可實現數據源動態切換

優化:

以上代碼是可行的,但是,需要讀數據庫的地方,就需要加上一大段RoutingDataSourceContext

ctx = ...代碼,使用起來十分不便。以下是優化方案

我們可以申明一個自定義注解,將以上RoutingDataSourceContext中的值,放在注解的value屬性中,

然后定義一個切面類,當我們在方法上標注自定義注解的時候,執行切面邏輯,獲取到注解中的值,set到RoutingDataSourceContext中,從而實現通過注解的方式,來動態切換數據源

以下是代碼實現:

注解類

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RoutingWith { String value() default 'master'; }

切面類:

@Aspect @Component public class RoutingAspect { @Around('@annotation(routingWith)') public Object routingWithDataSource(ProceedingJoinPoint joinPoint, RoutingWith routingWith) throws Throwable { String key = routingWith.value(); RoutingDataSourceContext ctx = new RoutingDataSourceContext(key); return joinPoint.proceed(); }}

改造Controller方法

@RoutingWith('masterDataSource') @GetMapping('/findAllProductM') public String findAllProductM() { productService.findAllProductM(); return 'lagou'; }@RoutingWith('slaveDataSource') @GetMapping('/findAllProductS') public String findAllProductS() { productService.findAllProductS(); return 'lagou'; }

到此這篇關于詳解SpringBoot+Mybatis實現動態數據源切換的文章就介紹到這了,更多相關SpringBoot+Mybatis動態數據源切換內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
中文字幕色婷婷在线视频| 久久不卡国产精品一区二区| 麻豆精品久久久| 欧美精品第一区| 亚洲精品成人图区| 国精品一区二区三区| 久久国产中文字幕| 六月丁香综合| 国产精品一区二区99| 国精品产品一区| 久久精品123| 热久久免费视频| 国产精品入口久久| 伊人久久av| 蜜桃免费网站一区二区三区| 欧美久久亚洲| 婷婷激情一区| 亚洲免费福利一区| 成人在线免费观看91| 999国产精品| 日韩精品视频网站| 久久精品资源| 亚洲国产不卡| 国产精品一区二区精品| 91精品国产福利在线观看麻豆| 久久亚洲色图| 精品欧美视频| 视频一区国产视频| 四季av一区二区凹凸精品| 噜噜噜躁狠狠躁狠狠精品视频 | 欧美日韩四区| 奇米777国产一区国产二区| 久久久国产精品入口麻豆| 国产91精品对白在线播放| 日韩av网站在线观看| 精精国产xxxx视频在线野外| 免费视频久久| 97欧美在线视频| 中文字幕一区二区三区日韩精品 | 国产欧美一区二区精品久久久 | 欧美日韩一区二区三区在线电影| 激情综合婷婷| 日本不卡不码高清免费观看| 日韩视频网站在线观看| 久久精品99国产精品日本| 91精品高清| 精品香蕉视频| 91午夜精品| 欧美日韩国产一区精品一区| 日韩av二区| 国产欧美日韩精品一区二区免费 | 欧美在线看片| 亚洲一区亚洲| 91看片一区| 麻豆国产精品视频| 欧美一区=区三区| 久久国产福利| 国产精品av久久久久久麻豆网| 国产福利一区二区精品秒拍| 一本一道久久a久久精品蜜桃| 牛牛精品成人免费视频| 久久最新视频| 久久精品国产www456c0m| 美女视频一区在线观看| 蜜臀91精品一区二区三区| 91亚洲国产| 国产福利一区二区三区在线播放| 亚洲一二三区视频| 亚洲成人精选| 99精品视频在线| 麻豆视频在线看| 精品视频黄色| 国产精品多人| 欧美一区免费| 亚洲另类视频| 六月丁香综合| 麻豆精品91| 亚洲欧美日韩视频二区| 美女少妇全过程你懂的久久| 亚洲天堂资源| 美女久久久久久 | 亚洲精品中文字幕乱码| 久久天堂av| 日韩电影免费网址| 成人在线黄色| 高清久久精品| 黄色aa久久| 伊人久久在线| 美女福利一区二区三区| 在线天堂中文资源最新版| 日韩av片子| 日韩精品麻豆| 久久精品青草| 国产主播一区| 国内精品福利| 99在线精品视频在线观看 | 桃色一区二区| 久久久久蜜桃| 伊人精品视频| 丝袜诱惑制服诱惑色一区在线观看| 性欧美69xoxoxoxo| 一级欧洲+日本+国产| 日韩午夜高潮| 中文字幕日韩高清在线| 香蕉久久久久久| 国产精品一卡| 麻豆一区二区在线| 国产中文在线播放| 99久久九九| 男人操女人的视频在线观看欧美| 久久影视三级福利片| 免费高潮视频95在线观看网站| 99热国内精品| 亚洲三级av| 久久精品国产亚洲aⅴ | 国产主播一区| 最近国产精品视频| 国产精品v亚洲精品v日韩精品| 精品中国亚洲| 性欧美videohd高精| 影音先锋久久| 欧美自拍一区| 日韩在线观看| 亚洲欧美网站在线观看| 里番精品3d一二三区| 91精品啪在线观看国产18| 中文字幕日韩欧美精品高清在线| 国产精品亚洲欧美一级在线| 日韩av首页| 日韩精品中文字幕吗一区二区| 精品国产中文字幕第一页 | 日本韩国欧美超级黄在线观看| 黄色亚洲精品| 日韩欧美久久| 国内在线观看一区二区三区| 一级欧洲+日本+国产| 欧美影院视频| se01亚洲视频 | 久久久精品网| 日本在线观看不卡视频| 久久精品五月| 午夜久久tv| 国产精品免费不| 91成人精品| 久久精品资源| 免费国产自久久久久三四区久久 | 91久久视频| 久久久久黄色| 国产农村妇女精品一区二区| 久久不见久久见免费视频7| 欧美日韩免费观看一区=区三区| 国产欧美69| 国模 一区 二区 三区| 国产欧美日韩一区二区三区四区| 婷婷丁香综合| 国产精品密蕾丝视频下载| 日韩视频不卡| 国产一区二区三区不卡av| 中文字幕av一区二区三区人| 国产成人精品一区二区免费看京| 亚洲精品大全| 欧美精品一区二区三区精品| 麻豆视频久久| 日本不卡在线视频| 亚洲精品网址| 久久久久国产精品一区二区| 久久精品一区二区三区中文字幕| 亚洲无线观看| 欧美日韩一二三四| 精品国产午夜| 欧美一级二区| 亚洲小说春色综合另类电影| 亚洲福利一区| 精品国产麻豆| 日本一不卡视频| 国产亚洲在线| 欧美日韩激情| 性感美女一区二区在线观看| 久久免费精品| 欧美日韩 国产精品| 亚洲丝袜美腿一区| 黄色成人精品网站| 婷婷成人综合| 中文字幕在线看片| 国产91在线播放精品| 国产精品xvideos88| 国产午夜久久av| 欧美日韩1区| 欧美啪啪一区| 中文字幕成人| 日韩精品一二三| 久久av在线| 日韩视频一区| 国产视频亚洲| 午夜影院欧美| 99热精品久久| 免费国产自久久久久三四区久久| 久久久亚洲一区| 色婷婷色综合| 97精品在线|