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

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

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

瀏覽:29日期: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
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
妖精视频成人观看www| 夜久久久久久| 久久国产高清| 国产欧美一区二区三区国产幕精品| 石原莉奈在线亚洲二区| 国产福利一区二区精品秒拍 | 精品国产一区二| 午夜精品久久久久久久久久蜜桃| 日韩中文字幕麻豆| 国产一区二区精品福利地址| 欧美色综合网| 国产精品久久久久久久免费软件| 欧美成人国产| 国产黄色一区| 免费看黄色91| 日韩av网站在线免费观看| 欧美1区2区3| 久久夜色精品| 久久久久蜜桃| 在线日韩成人| 亚洲一区二区毛片| 毛片不卡一区二区| 久久婷婷久久| 你懂的国产精品| 国产日韩欧美一区二区三区在线观看 | 久久精品免视看国产成人| 97精品97| 手机精品视频在线观看| 日本精品影院| 激情婷婷欧美| 国产日韩欧美在线播放不卡| 亚洲精品国产日韩| 91久久久久| 国产毛片一区| 亚洲国产一区二区三区在线播放 | 欧美在线观看天堂一区二区三区| 91欧美日韩| 久久精品国内一区二区三区水蜜桃| 亚洲精品自拍| 成人午夜国产| 亚洲一区日韩| 日韩免费av| av一区二区高清| 日韩一区二区三区免费视频 | 黄色成人91| 国产精品美女久久久浪潮软件| 伊人久久在线| 国产精品亲子伦av一区二区三区| 国产亚洲欧美日韩在线观看一区二区 | 日韩av网站在线免费观看| 久久久久美女| 老司机精品在线| 日韩不卡一区二区三区| 五月天综合网站| 黑森林国产精品av| 国产精品网在线观看| 亚洲天堂免费| 久久亚洲国产| 日本在线观看不卡视频| 亚洲精品一区二区在线看| 国内不卡的一区二区三区中文字幕| 欧美在线精品一区| 亚洲色诱最新| 国产福利片在线观看| 亚洲精品第一| av中文字幕在线观看第一页 | 久久精品国产www456c0m| 国产a久久精品一区二区三区| 神马午夜久久| 伊人久久大香线蕉av不卡| 久久久久免费| 国产毛片久久| 久久精品影视| 乱一区二区av| 日韩三级精品| 久久中文字幕二区| 清纯唯美亚洲综合一区| 私拍精品福利视频在线一区| 日本一区二区三区中文字幕| 亚洲精品一区二区在线看| 久久一区精品| 欧美在线看片| 国产精品一区免费在线| 亚洲精品美女91| 国产伦精品一区二区三区视频| 自拍日韩欧美| 国产一区二区三区不卡av| 亚洲精品在线国产| 黄色不卡一区| 国产成年精品| 夜夜精品视频| 国产视频一区二| 爽好多水快深点欧美视频| 亚洲高清影视| 免费看的黄色欧美网站| 美女精品在线| 日本三级亚洲精品| 欧美精品影院| 日韩成人高清| 欧美13videosex性极品| 国产精品chinese| 日本中文字幕一区二区| 国产在线欧美| 麻豆91精品视频| 国产亚洲欧美日韩精品一区二区三区 | 国产v日韩v欧美v| 国产精品99一区二区三| 国产福利91精品一区二区| 欧美国产不卡| 91免费精品| 欧美91在线| 88xx成人免费观看视频库| 国产模特精品视频久久久久| 日韩在线观看一区二区| 日本在线不卡视频| 久久精选视频| 福利一区和二区| 热三久草你在线| 麻豆亚洲精品| 精品三级国产| 国产精品a级| 国产毛片精品久久| 国产成人久久精品麻豆二区 | xxxxx性欧美特大| 日本视频一区二区| 精品国产一区二| 不卡视频在线| 欧美日韩一区二区国产 | 欧美影院三区| 黄色不卡一区| 午夜在线播放视频欧美| 国产日韩高清一区二区三区在线 | 国产一区国产二区国产三区| 色天使综合视频| 亚洲精品综合| 宅男噜噜噜66国产日韩在线观看| 欧美精品不卡| 亚洲三区欧美一区国产二区| 999久久久国产精品| 日韩亚洲在线| 国产精选久久| 久久青青视频| 亚洲精品一级| 老司机精品视频网| 日本aⅴ免费视频一区二区三区| 午夜在线精品偷拍| 国产日产精品一区二区三区四区的观看方式| 欧美在线观看视频一区| 久久国产高清| 麻豆精品视频在线观看免费| 成人三级高清视频在线看| 久久福利毛片| 久久美女性网| 婷婷精品在线观看| 精品91久久久久| 91精品99| 国产美女精品| 国产情侣久久| 日韩福利视频网| 午夜日本精品| 蜜臀91精品国产高清在线观看| 卡一卡二国产精品| **爰片久久毛片| 国产精品乱战久久久| 国产精品久久久久久久久久久久久久久| 91精品丝袜国产高跟在线| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产夫妻在线| 黑人精品一区| 91日韩免费| 国产高清精品二区| 久久久久伊人| 精品美女在线视频| 久久久久国产| 一区在线视频观看| 日韩高清二区| 精品国产18久久久久久二百| 日韩av福利| 日韩福利一区| 日韩久久视频| 久久婷婷av| 91av一区| 日韩精品一区二区三区免费观影| 99国产精品自拍| 亚洲视频电影在线| www在线观看黄色| 亚洲视频电影在线| 中文视频一区| 亚洲欧洲免费| 国产精品视频一区视频二区| 久久中文精品| 亚洲va中文在线播放免费| 久久精品人人| 视频一区免费在线观看| 久久精品三级| 日本亚洲最大的色成网站www| 岛国av在线网站| 欧美激情国产在线| 欧美91福利在线观看| 欧美影院精品|