成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

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

SpringBoot+Mybatis-Plus實現mysql讀寫分離方案的示例代碼

瀏覽:6日期:2023-02-05 17:35:32

1. 引入mybatis-plus相關包,pom.xml文件

SpringBoot+Mybatis-Plus實現mysql讀寫分離方案的示例代碼

2. 配置文件application.property增加多庫配置

mysql 數據源配置

spring.datasource.primary.jdbc-url=jdbc:mysql://xx.xx.xx.xx:3306/portal?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&characterEncoding=utf8&serverTimezone=GMT%2B8spring.datasource.primary.username=rootspring.datasource.primary.password=rootspring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver#mysql slave 數據源配置spring.datasource.slave.jdbc-url=jdbc:mysql://xx.xx.xx.xx:3306/portal?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&characterEncoding=utf8&serverTimezone=GMT%2B8spring.datasource.slave.username=rootspring.datasource.slave.password=rootspring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver

3. 配置數據源及注解

數據源配置 MultiDataSourceConfig.Java

/** * 配置多數據源 */@Profile('dev')//開發模式配置文件@Configuration@MapperScan(basePackages = 'com.csc.portal.mapper')//掃描包public class MultiDataSourceConfig { /** * 主數據源 * @return */ @Bean @ConfigurationProperties(prefix = 'spring.datasource.primary') public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } /** * 從數據源 * @return */ @Bean @ConfigurationProperties(prefix = 'spring.datasource.slave') public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } /** * 路由數據源,前面兩個數據源是為了創建此數據源 * @param masterDataSource 主數據源 * @param slaveDataSource 從數據源 * @return */ @Bean public DataSource myRoutingDataSource(@Qualifier('masterDataSource') DataSource masterDataSource, @Qualifier('slaveDataSource') DataSource slaveDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DBTypeEnum.MASTER, masterDataSource); targetDataSources.put(DBTypeEnum.SLAVE, slaveDataSource); MyRoutingDataSource myRoutingDataSource = new MyRoutingDataSource(); myRoutingDataSource.setDefaultTargetDataSource(slaveDataSource);//設置默認數據源 myRoutingDataSource.setTargetDataSources(targetDataSources);//設置路由表,使用map的key,value方式得到對應數據源 return myRoutingDataSource; }

數據庫枚舉類

public enum DBTypeEnum { MASTER, SLAVE;}

注解

@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface Master {}

@Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface Slave {}

4. Mybatis-plus配置

@EnableTransactionManagement@Configuration@MapperScan(basePackages = 'com.csc.portal.mapper')public class MybatisPlusConfig { /** * 分頁插件 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } @Resource(name = 'myRoutingDataSource') private DataSource myRoutingDataSource; /** * 使用MyBatis Plus的sqlSessionFactory代替, * 此處注意mybatis與mybatisPlus的配置不同,不然掃描不到對數據操作的方法。會報未綁定錯誤 * @return sqlSessionFactory * @throws Exception */ @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(myRoutingDataSource); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources('classpath:mapper/*.xml')); MybatisConfiguration mybatisConfiguration = new MybatisConfiguration(); sqlSessionFactoryBean.setConfiguration(mybatisConfiguration); return sqlSessionFactoryBean.getObject(); } /** * 此處為使用mybatis時的sqlsessionFactory配置 * @return * @throws Exception */ /* @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(myRoutingDataSource); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources('classpath:mapper/*.xml')); return sqlSessionFactoryBean.getObject(); } */ /** * 事務配置 * @return 事務管理器 */ @Bean public DataSourceTransactionManager transactionManager() { DataSourceTransactionManager tx = new DataSourceTransactionManager(); tx.setDataSource(myRoutingDataSource); return tx; }

5. 增加數據源管理類

DBContextHolder.java

public class DBContextHolder { /** * 外部一個請求將會產生一個線程與之對應,每個線程的變量可用ThreadLocal進行存儲 */ private static final ThreadLocal<DBTypeEnum> contextHolder = new ThreadLocal<>(); public static void set(DBTypeEnum dbType) { contextHolder.set(dbType); } public static DBTypeEnum get() { return contextHolder.get(); } public static void master() { set(DBTypeEnum.MASTER); System.out.println('切換到master'); } public static void slave() { set(DBTypeEnum.SLAVE); System.out.println('切換到slave'); }}

指定選擇數據源

MyRoutingDataSource.java 方法determineCurrentLookupKey決定最終使用哪個數據源進行操作,若為空則使用默認數據源。

public class MyRoutingDataSource extends AbstractRoutingDataSource { @Nullable @Override protected Object determineCurrentLookupKey() { System.out.println('線程名:'+Thread.currentThread().getName()+':'+DBContextHolder.get()); return DBContextHolder.get();/* if (DBContextHolder.get() != null) { System.out.println('線程名:'+Thread.currentThread().getName()+':'+DBContextHolder.get()); return DBContextHolder.get(); } else { System.out.println('未匹配到指定數據庫,默認切換到Master'); return DBTypeEnum.MASTER; }*/ //return DBContextHolder.get(); }}

6. 增加aop切面

@Aspect@Component@Order(0)//配置注解優先級,優于事物注解@Transactional先進行數據源切換,//不然在事物中進行數據源切換無效public class DataSourceAop { @Pointcut(/*'!@annotation(com.csc.portal.annotation.Master) ' + '&& (execution(* com.csc.portal.service..*.select*(..)) ' + '|| execution(* com.csc.portal.service..*.get*(..))'+*/ ' @annotation(com.csc.portal.annotation.Slave)') public void readPointcut() { } @Pointcut('@annotation(com.csc.portal.annotation.Master) ' //+ /* '|| execution(* com.csc.portal.service..*.insert*(..)) ' + '|| execution(* com.csc.portal.service..*.add*(..)) ' + '|| execution(* com.csc.portal.service..*.update*(..)) ' + '|| execution(* com.csc.portal.service..*.edit*(..)) ' + '|| execution(* com.csc.portal.service..*.delete*(..)) ' + '|| execution(* com.csc.portal.service..*.remove*(..))'*/) public void writePointcut() { } @Before('readPointcut()') public void read() { //獲取攔截類 DBContextHolder.slave(); System.out.println(Thread.currentThread().getName()+DBContextHolder.get()); } @Before('writePointcut()') public void write() { //獲取攔截類/* String className = pjp.getTarget().getClass().getName(); System.out.println('當前線程'+Thread.currentThread().getName()+' 攔截類為:' + className); //獲取攔截的方法名 MethodSignature msig = (MethodSignature) pjp.getSignature(); Method currentMethod = null; try { currentMethod = pjp.getTarget().getClass().getMethod(msig.getName(), msig.getParameterTypes()); } catch (NoSuchMethodException e) { e.printStackTrace(); } String methodName = currentMethod.getName(); System.out.println('攔截方法名為:' + methodName);*/ DBContextHolder.master(); System.out.println(Thread.currentThread().getName()+DBContextHolder.get()); } }

6. 實際應用

在service層方法前增加注解@Master表示使用主庫,進行增刪改的操作使用主庫。 在service層方法前增加注解@Slave表示使用從庫,進行查的操作使用從庫,默認使用從庫,可不配置。 @ Transactional注解加到service層,增加了@Transactional注解后,啟用事務后,一個事務內部的connection是復用的,所以就算AOP切了數據源字符串,但是數據源并不會被真正修改。所以@Transactional注解不要寫在controller層,不然在service層也切換不了數據源。 @Transactional與@Master可同時使用,已經配置@Master注解的優先級較高,先切換數據源后執行事務。

到此這篇關于SpringBoot+Mybatis-Plus實現mysql讀寫分離方案的示例代碼的文章就介紹到這了,更多相關SpringBoot Mybatis-Plus mysql讀寫分離內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
日韩一区欧美二区| 91精品国产综合久久久久久| 色先锋久久av资源部| 亚洲蜜臀av乱码久久精品| 午夜精品短视频| 久久无码av三级| 成人免费毛片a| 日韩欧美激情一区| 成人毛片老司机大片| 欧美系列一区二区| 丝袜国产日韩另类美女| 久久九九免费| 日本aⅴ精品一区二区三区 | 91免费国产在线观看| 欧美成va人片在线观看| 高清不卡在线观看| 欧美成人在线直播| fc2成人免费人成在线观看播放| 欧美精品一区二区久久久| 菠萝蜜视频在线观看一区| 欧美精品一区二区在线观看| av在线不卡网| 久久亚洲私人国产精品va媚药| 不卡av在线网| 中文字幕乱码亚洲精品一区 | 国产精品国产三级欧美二区| 国产亚洲一区二区三区四区 | 国产日韩1区| 一区二区三区中文免费| 国产日韩精品久久| 日韩制服丝袜先锋影音| 欧美日韩久久久久久| 福利一区二区在线观看| 日韩欧美国产成人一区二区| 成人动漫视频在线| 国产日产欧美一区二区三区| 在线欧美福利| 亚洲福利视频导航| 欧美日韩在线免费视频| 国产传媒一区在线| 久久久久国产精品人| 一区久久精品| 午夜在线电影亚洲一区| 欧美亚洲免费在线一区| 国产一区二区在线电影| 精品国产乱码久久久久久蜜臀| 欧美一区高清| 亚洲丝袜美腿综合| 亚洲综合激情| 国产综合色产在线精品| 久久亚洲影视婷婷| 国产亚洲高清视频| 麻豆精品国产传媒mv男同| 欧美α欧美αv大片| 国产在线欧美日韩| 亚洲成av人片在线观看| 欧美丰满高潮xxxx喷水动漫| 欧美一区二区三区在线播放| 亚洲精品欧美激情| 欧美日韩小视频| 欧美一区高清| 婷婷激情综合网| 日韩免费高清视频| 国产综合自拍| 人人狠狠综合久久亚洲| 欧美精品一区二区三区蜜臀| 亚洲经典一区| 久久成人av少妇免费| 久久综合国产精品| 欧美一级二区| 国产iv一区二区三区| 亚洲欧洲日韩综合一区二区| 色吧成人激情小说| 成人毛片视频在线观看| 一区二区三区在线免费视频| 色综合久久久网| 成人高清伦理免费影院在线观看| 亚洲美女视频一区| 欧美影片第一页| 91浏览器打开| 日韩国产成人精品| 久久久激情视频| 久久午夜激情| 91亚洲精品一区二区乱码| 亚洲一区二区精品视频| 日韩精品专区在线| 国产日韩免费| 成人免费看视频| 一区二区激情小说| 精品久久久久久久久久久久久久久久久| 中文在线不卡| 成人国产精品视频| 首页亚洲欧美制服丝腿| 欧美制服丝袜第一页| 欧美~级网站不卡| 精品一区二区三区欧美| 欧美国产一区二区| 欧洲视频一区二区| 欧美精品大片| 精品一区二区国语对白| 成人免费在线观看入口| 欧美精品v日韩精品v韩国精品v| 亚洲美女少妇无套啪啪呻吟| 国产一区二区0| 亚洲国产精品欧美一二99| 久久噜噜亚洲综合| 欧美另类z0zxhd电影| 91久久精品国产91久久性色tv | 99免费精品在线| 午夜精品福利一区二区三区av| 久久中文字幕电影| 欧美三级资源在线| 亚洲欧洲一二三| 国产**成人网毛片九色| 五月婷婷激情综合网| 国产网站一区二区三区| 欧美日韩一区二区三区在线看 | 亚洲va欧美va人人爽午夜 | 日韩欧美综合在线| 免费看的黄色欧美网站| 91视频免费观看| 蜜臀91精品一区二区三区| 国产精品国产三级国产aⅴ入口 | 国产一区二区三区的电影| 成人黄色网址在线观看| 一区二区三区不卡视频在线观看| 日韩精品一区二区三区在线播放| 久久久久久久波多野高潮日日| 91亚洲精品久久久蜜桃| 精品亚洲porn| 亚洲h精品动漫在线观看| 中文字幕av一区 二区| 欧美乱妇15p| 久久免费高清| 亚洲伦理精品| 欧美日韩高清在线一区| 国产精品综合在线视频| 亚洲高清不卡在线观看| 中文字幕av免费专区久久| 91精品国产高清一区二区三区| 性色一区二区三区| 91香蕉视频在线| 国产成人精品影视| 美女视频黄a大片欧美| 一区二区在线观看免费| 国产偷国产偷精品高清尤物| 欧美精品在线观看播放| 久久久夜精品| 国产欧美成人| 亚洲高清视频在线观看| 91免费看片在线观看| 国产福利91精品| 日韩av电影免费观看高清完整版 | 成人小视频免费在线观看| 首页亚洲欧美制服丝腿| 欧美理论片在线| 欧美午夜精品一区二区三区| 国产日本精品| 日韩视频二区| 国产一区高清视频| 欧美一区二区三区免费看| 成人午夜免费av| 国产在线视频不卡二| 蜜臀久久久99精品久久久久久| 亚洲成人免费视| 亚洲精品中文在线观看| 中文字幕欧美三区| 久久久精品国产免费观看同学| 欧美成人精品3d动漫h| 欧美日本不卡视频| 欧美视频自拍偷拍| 欧日韩精品视频| 欧美性猛交一区二区三区精品| 亚洲免费网址| 亚洲一区二区成人| 午夜一区在线| 久久精品国产第一区二区三区最新章节| 国产日韩欧美一区在线| 99在线精品免费视频九九视| 亚洲黄色天堂| 日韩视频免费| 亚洲一区二区毛片| 国产视频一区在线观看一区免费| 亚洲精品乱码久久久久久蜜桃91| 很黄很黄激情成人| 激情久久久久| 亚洲精品欧美精品| 欧美亚洲免费高清在线观看| 美女图片一区二区| 久久久久久久欧美精品| 91电影在线观看| 欧美日本在线看| 日韩欧美一级二级三级久久久| 精品国产123| 久久久高清一区二区三区| 久久精品亚洲乱码伦伦中文 | 在线观看一区二区精品视频| 欧美三级蜜桃2在线观看| 欧美日本国产视频| 26uuu精品一区二区|