亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

詳解SpringBoot+Mybatis實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換

瀏覽:15日期:2023-03-12 18:32:54
業(yè)務(wù)背景

電商訂單項(xiàng)目分正向和逆向兩個(gè)部分:其中正向數(shù)據(jù)庫(kù)記錄了訂單的基本信息,包括訂單基本信息、訂單商品信息、優(yōu)惠卷信息、發(fā)票信息、賬期信息、結(jié)算信息、訂單備注信息、收貨人信息等;逆向數(shù)據(jù)庫(kù)主要包含了商品的退貨信息和維修信息。數(shù)據(jù)量超過(guò)500萬(wàn)行就要考慮分庫(kù)分表和讀寫分離,那么我們?cè)谡虿僮骱湍嫦虿僮鞯臅r(shí)候,就需要?jiǎng)討B(tài)的切換到相應(yīng)的數(shù)據(jù)庫(kù),進(jìn)行相關(guān)的操作。

解決思路

現(xiàn)在項(xiàng)目的結(jié)構(gòu)設(shè)計(jì)基本上是基于MVC的,那么數(shù)據(jù)庫(kù)的操作集中在dao層完成,主要業(yè)務(wù)邏輯在service層處理,controller層處理請(qǐng)求。假設(shè)在執(zhí)行dao層代碼之前能夠?qū)?shù)據(jù)源(DataSource)換成我們想要執(zhí)行操作的數(shù)據(jù)源,那么這個(gè)問(wèn)題就解決了

環(huán)境準(zhǔn)備:

1.實(shí)體類

@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); } }具體實(shí)現(xiàn)

第一步:配置多數(shù)據(jù)源

首先,我們?cè)赼pplication.properties中配置兩個(gè)數(shù)據(jù)源

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的配置代碼中,我們初始化兩個(gè)數(shù)據(jù)源:@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內(nèi)置的RoutingDataSource,把兩個(gè)真實(shí)的數(shù)據(jù)源代理為一個(gè)動(dòng)態(tài)數(shù)據(jù)源:

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

第三步:編寫RoutingDataSourceContext用于存儲(chǔ)當(dāng)前需要切換為哪個(gè)數(shù)據(jù)源

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(); }}

測(cè)試(一下代碼為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';}

以上代碼即可實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)切換

優(yōu)化:

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

ctx = ...代碼,使用起來(lái)十分不便。以下是優(yōu)化方案

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

然后定義一個(gè)切面類,當(dāng)我們?cè)诜椒ㄉ蠘?biāo)注自定義注解的時(shí)候,執(zhí)行切面邏輯,獲取到注解中的值,set到RoutingDataSourceContext中,從而實(shí)現(xiàn)通過(guò)注解的方式,來(lái)動(dòng)態(tài)切換數(shù)據(jù)源

以下是代碼實(shí)現(xiàn):

注解類

@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'; }

到此這篇關(guān)于詳解SpringBoot+Mybatis實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的文章就介紹到這了,更多相關(guān)SpringBoot+Mybatis動(dòng)態(tài)數(shù)據(jù)源切換內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 天天色图| 国产精品亚洲精品日韩已方 | 日韩黄色大片免费看 | 久久亚洲精品一区成人 | 59pao成国产成视频永久免费 | 国产高清天干天天美女 | 黄图视频在线观看 | 久久99国产精一区二区三区 | 婷婷影院在线综合免费视频 | 国产成人免费观看在线视频 | 欧美日产欧美日产精品 | 成人夜色视频 | 国产一区二区影院 | 亚洲国产成人久久 | 香蕉午夜| 在线成年视频免费观看 | 欧美日韩午夜精品不卡综合 | 538精品视频 | 国产精品黄网站免费观看 | 黄色骚片 | 亚洲人成影院在线高清 | 国产美女一区 | 日批国产 | 一区二区美女视频 | 日韩国产午夜一区二区三区 | 国产精品国产三级国产普通话对白 | 国产一级爱片在线播放 | 九九爱www高清免费人成 | 男女啪啪成人免费网站 | 高清一级做a爱视频免费 | 欧美精品免费线视频观看视频 | 免费碰碰视频 | 色视频在线免费观看 | 黄网页在线观看 | 久久精品a亚洲国产v高清不卡 | 亚洲综合丁香婷婷六月香 | 亚洲综合91社区精品福利 | 欧美日本日韩 | 特级毛片永久久免费观看 | 香蕉人精品视频多人免费永久视频 | 亚洲香蕉国产高清在线播放 |