本篇內容主要講解“怎么用SpringBoot + Mybatis多數(shù)據(jù)源配置實現(xiàn)讀寫分離”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么用SpringBoot + Mybatis多數(shù)據(jù)源配置實現(xiàn)讀寫分離”吧!
創(chuàng)新互聯(lián)建站堅持“要么做到,要么別承諾”的工作理念,服務領域包括:網(wǎng)站制作、成都網(wǎng)站建設、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的博興網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!
應用場景:項目中有一些報表統(tǒng)計與查詢功能,對數(shù)據(jù)實時性要求不高,因此考慮對報表的統(tǒng)計與查詢去操作slave db,減少對master的壓力。
根據(jù)網(wǎng)上多份資料測試發(fā)現(xiàn)總是使用master數(shù)據(jù)源,無法切換到slave,經過多次調試修改現(xiàn)已完美通過,現(xiàn)整理下詳細步驟和完整代碼如下:
實現(xiàn)方式:配置多個數(shù)據(jù)源,使用Spring AOP實現(xiàn)攔截注解實現(xiàn)數(shù)據(jù)源的動態(tài)切換。
1. application.yml數(shù)據(jù)庫配置:
druid: type: com.alibaba.druid.pool.DruidDataSource master: url: jdbc:MySQL://127.0.0.1:3306/test?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true driver-class-name: com.mysql.jdbc.Driver username: test password: 123 initial-size: 5 max-active: 10 min-idle: 5 max-wait: 60000 time-between-eviction-runs-millis: 3000 min-evictable-idle-time-millis: 300000 validation-query: SELECT 'x' FROM DUAL test-while-idle: true test-on-borrow: true test-on-return: false filters: stat,wall,log4j2 slave: url: jdbc:mysql://127.0.0.1:3307/test?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true driver-class-name: com.mysql.jdbc.Driver username: test password: 123 initial-size: 5 max-active: 10 min-idle: 5 max-wait: 60000 time-between-eviction-runs-millis: 3000 min-evictable-idle-time-millis: 300000 validation-query: SELECT 'x' FROM DUAL test-while-idle: true test-on-borrow: true test-on-return: false filters: stat,wall,log4j2
2. 通過MybatisAutoConfiguration實現(xiàn)多數(shù)據(jù)源注入:
@Configuration @EnableTransactionManagement public class DataSourceConfiguration extends MybatisAutoConfiguration { @Value("${druid.type}") private Class<? extends DataSource> dataSourceType; @Bean(name = "masterDataSource") @Primary @ConfigurationProperties(prefix = "druid.master") public DataSource masterDataSource(){ return DataSourceBuilder.create().type(dataSourceType).build(); } @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "druid.slave") public DataSource slaveDataSource(){ return DataSourceBuilder.create().type(dataSourceType).build(); } @Bean @Override public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { return super.sqlSessionFactory(dataSource()); } @Bean(name = "dataSource") public AbstractRoutingDataSource dataSource() { MasterSlaveRoutingDataSource proxy = new MasterSlaveRoutingDataSource(); Map<Object, Object> targetDataResources = new HashMap<>(); targetDataResources.put(DbContextHolder.DbType.MASTER, masterDataSource()); targetDataResources.put(DbContextHolder.DbType.SLAVE, slaveDataSource()); proxy.setDefaultTargetDataSource(masterDataSource()); proxy.setTargetDataSources(targetDataResources); proxy.afterPropertiesSet(); return proxy; } }
3. 基于 AbstractRoutingDataSource 和 AOP 的多數(shù)據(jù)源的配置
我們自己定義一個DataSource類,來繼承 AbstractRoutingDataSource:
public class MasterSlaveRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DbContextHolder.getDbType(); } }
這里通過determineCurrentLookupKey()返回的不同key到sqlSessionFactory中獲取對應數(shù)據(jù)源然后使用ThreadLocal來存放線程的變量,將不同的數(shù)據(jù)源標識記錄在ThreadLocal中
public class DbContextHolder { public enum DbType{ MASTER, SLAVE } private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<>(); public static void setDbType(DbType dbType){ if (dbType==null) { throw new NullPointerException(); } contextHolder.set(dbType); } public static DbType getDbType(){ return contextHolder.get()==null?DbType.MASTER:contextHolder.get(); } public static void clearDbType(){ contextHolder.remove(); } }
4. 注解實現(xiàn)
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ReadOnlyConnection { }@Aspect @Component public class ReadOnlyConnectionInterceptor implements Ordered { @Around("@annotation(readOnlyConnection)") public Object proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throws Throwable { try { DbContextHolder.setDbType(DbContextHolder.DbType.SLAVE); Object result = proceedingJoinPoint.proceed(); return result; }finally { DbContextHolder.clearDbType(); } } @Override public int getOrder() { return 0; } }
5. 應用方式:
service層接口增加ReadOnlyConnection注解即可:
@ReadOnlyConnectionpublic CommonPagingVO<GroupGoodsVO> pagingByCondition(GroupGoodsCondition condition, int pageNum, int pageSize) { Page<GroupGoodsVO> page = PageHelper.startPage(pageNum, pageSize).doSelectPage(() -> groupGoodsMapper.listByCondition(condition)); return CommonPagingVO.get(page,page.getResult()); }
對于未加ReadOnlyConnection注解的默認使用masterDataSource。
到此,相信大家對“怎么用SpringBoot + Mybatis多數(shù)據(jù)源配置實現(xiàn)讀寫分離”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
當前標題:怎么用SpringBoot+Mybatis多數(shù)據(jù)源配置實現(xiàn)讀寫分離
網(wǎng)頁地址:http://m.rwnh.cn/article44/igjohe.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站制作、手機網(wǎng)站建設、建站公司、定制開發(fā)、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)