SpringBoot+Mybatis-Plus實(shí)現(xiàn)mysql讀寫(xiě)分離方案的示例代碼
1. 引入mybatis-plus相關(guān)包,pom.xml文件

2. 配置文件application.property增加多庫(kù)配置
mysql 數(shù)據(jù)源配置
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 數(shù)據(jù)源配置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. 配置數(shù)據(jù)源及注解
數(shù)據(jù)源配置 MultiDataSourceConfig.Java
/** * 配置多數(shù)據(jù)源 */@Profile('dev')//開(kāi)發(fā)模式配置文件@Configuration@MapperScan(basePackages = 'com.csc.portal.mapper')//掃描包public class MultiDataSourceConfig { /** * 主數(shù)據(jù)源 * @return */ @Bean @ConfigurationProperties(prefix = 'spring.datasource.primary') public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } /** * 從數(shù)據(jù)源 * @return */ @Bean @ConfigurationProperties(prefix = 'spring.datasource.slave') public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } /** * 路由數(shù)據(jù)源,前面兩個(gè)數(shù)據(jù)源是為了創(chuàng)建此數(shù)據(jù)源 * @param masterDataSource 主數(shù)據(jù)源 * @param slaveDataSource 從數(shù)據(jù)源 * @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);//設(shè)置默認(rèn)數(shù)據(jù)源 myRoutingDataSource.setTargetDataSources(targetDataSources);//設(shè)置路由表,使用map的key,value方式得到對(duì)應(yīng)數(shù)據(jù)源 return myRoutingDataSource; }
數(shù)據(jù)庫(kù)枚舉類(lèi)
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 { /** * 分頁(yè)插件 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } @Resource(name = 'myRoutingDataSource') private DataSource myRoutingDataSource; /** * 使用MyBatis Plus的sqlSessionFactory代替, * 此處注意mybatis與mybatisPlus的配置不同,不然掃描不到對(duì)數(shù)據(jù)操作的方法。會(huì)報(bào)未綁定錯(cuò)誤 * @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時(shí)的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(); } */ /** * 事務(wù)配置 * @return 事務(wù)管理器 */ @Bean public DataSourceTransactionManager transactionManager() { DataSourceTransactionManager tx = new DataSourceTransactionManager(); tx.setDataSource(myRoutingDataSource); return tx; }
5. 增加數(shù)據(jù)源管理類(lèi)
DBContextHolder.java
public class DBContextHolder { /** * 外部一個(gè)請(qǐng)求將會(huì)產(chǎn)生一個(gè)線(xiàn)程與之對(duì)應(yīng),每個(gè)線(xiàn)程的變量可用ThreadLocal進(jìn)行存儲(chǔ) */ 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'); }}
指定選擇數(shù)據(jù)源
MyRoutingDataSource.java 方法determineCurrentLookupKey決定最終使用哪個(gè)數(shù)據(jù)源進(jìn)行操作,若為空則使用默認(rèn)數(shù)據(jù)源。
public class MyRoutingDataSource extends AbstractRoutingDataSource { @Nullable @Override protected Object determineCurrentLookupKey() { System.out.println('線(xiàn)程名:'+Thread.currentThread().getName()+':'+DBContextHolder.get()); return DBContextHolder.get();/* if (DBContextHolder.get() != null) { System.out.println('線(xiàn)程名:'+Thread.currentThread().getName()+':'+DBContextHolder.get()); return DBContextHolder.get(); } else { System.out.println('未匹配到指定數(shù)據(jù)庫(kù),默認(rèn)切換到Master'); return DBTypeEnum.MASTER; }*/ //return DBContextHolder.get(); }}
6. 增加aop切面
@Aspect@Component@Order(0)//配置注解優(yōu)先級(jí),優(yōu)于事物注解@Transactional先進(jìn)行數(shù)據(jù)源切換,//不然在事物中進(jìn)行數(shù)據(jù)源切換無(wú)效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() { //獲取攔截類(lèi) DBContextHolder.slave(); System.out.println(Thread.currentThread().getName()+DBContextHolder.get()); } @Before('writePointcut()') public void write() { //獲取攔截類(lèi)/* String className = pjp.getTarget().getClass().getName(); System.out.println('當(dāng)前線(xiàn)程'+Thread.currentThread().getName()+' 攔截類(lèi)為:' + 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. 實(shí)際應(yīng)用
在service層方法前增加注解@Master表示使用主庫(kù),進(jìn)行增刪改的操作使用主庫(kù)。 在service層方法前增加注解@Slave表示使用從庫(kù),進(jìn)行查的操作使用從庫(kù),默認(rèn)使用從庫(kù),可不配置。 @ Transactional注解加到service層,增加了@Transactional注解后,啟用事務(wù)后,一個(gè)事務(wù)內(nèi)部的connection是復(fù)用的,所以就算AOP切了數(shù)據(jù)源字符串,但是數(shù)據(jù)源并不會(huì)被真正修改。所以@Transactional注解不要寫(xiě)在controller層,不然在service層也切換不了數(shù)據(jù)源。 @Transactional與@Master可同時(shí)使用,已經(jīng)配置@Master注解的優(yōu)先級(jí)較高,先切換數(shù)據(jù)源后執(zhí)行事務(wù)。到此這篇關(guān)于SpringBoot+Mybatis-Plus實(shí)現(xiàn)mysql讀寫(xiě)分離方案的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot Mybatis-Plus mysql讀寫(xiě)分離內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. ASP新手必備的基礎(chǔ)知識(shí)2. asp文件用什么軟件編輯3. CentOS郵箱服務(wù)器搭建系列——SMTP服務(wù)器的構(gòu)建( Postfix )4. PHP基礎(chǔ)之生成器4——比較生成器和迭代器對(duì)象5. JAVA 實(shí)現(xiàn)延遲隊(duì)列的方法6. JS中6個(gè)對(duì)象數(shù)組去重的方法7. vue+element開(kāi)發(fā)一個(gè)谷歌插件的全過(guò)程8. Vue axios獲取token臨時(shí)令牌封裝案例9. 通過(guò)IEAD+Maven快速搭建SSM項(xiàng)目的過(guò)程(Spring + Spring MVC + Mybatis)10. 利用CSS制作3D動(dòng)畫(huà)

網(wǎng)公網(wǎng)安備