一文帶你搞定SpringCloud集成MybatisPlus實(shí)現(xiàn)MySQL多數(shù)據(jù)源配置
一、開篇引入
圖片
在當(dāng)今互聯(lián)網(wǎng)應(yīng)用開發(fā)的大環(huán)境下,業(yè)務(wù)場(chǎng)景日益復(fù)雜,數(shù)據(jù)量也呈爆炸式增長(zhǎng)。就拿一個(gè)電商系統(tǒng)來說,用戶數(shù)據(jù)和訂單數(shù)據(jù)量都非常龐大。為了更好地管理和維護(hù)數(shù)據(jù),提高系統(tǒng)性能,我們通常會(huì)將不同類型的數(shù)據(jù)存儲(chǔ)在不同的數(shù)據(jù)庫(kù)中,比如將用戶數(shù)據(jù)存儲(chǔ)在一個(gè)數(shù)據(jù)庫(kù),訂單數(shù)據(jù)存儲(chǔ)在另一個(gè)數(shù)據(jù)庫(kù)。這就涉及到多數(shù)據(jù)源的配置問題。
在 SpringCloud 微服務(wù)架構(gòu)中,我們經(jīng)常會(huì)使用 MybatisPlus 來操作數(shù)據(jù)庫(kù)。那么如何在 SpringCloud 中集成 MybatisPlus,實(shí)現(xiàn) MySQL 多數(shù)據(jù)源配置呢?這就是我們今天要探討的問題。接下來,我將一步一步地帶領(lǐng)大家實(shí)現(xiàn)這個(gè)配置,讓我們開始吧!
二、基礎(chǔ)概念科普
圖片
(一)SpringCloud
SpringCloud 是一系列框架的有序集合,它構(gòu)建在 Spring Boot 之上,為分布式系統(tǒng)開發(fā)提供了豐富的工具和組件 ,極大地簡(jiǎn)化了分布式系統(tǒng)的開發(fā)過程。
SpringCloud 擁有眾多強(qiáng)大的功能,在服務(wù)治理方面,像 Eureka 這樣的組件,能實(shí)現(xiàn)服務(wù)的注冊(cè)與發(fā)現(xiàn),讓各個(gè)微服務(wù)之間可以輕松找到彼此并進(jìn)行通信。舉個(gè)例子,在一個(gè)大型電商系統(tǒng)中,訂單服務(wù)、商品服務(wù)等多個(gè)微服務(wù)可以通過 Eureka 進(jìn)行注冊(cè),當(dāng)訂單服務(wù)需要調(diào)用商品服務(wù)獲取商品信息時(shí),就能通過 Eureka 快速找到商品服務(wù)的地址并發(fā)起請(qǐng)求。
在負(fù)載均衡領(lǐng)域,Ribbon 組件大展身手,它可以將客戶端的請(qǐng)求均勻地分發(fā)到多個(gè)服務(wù)實(shí)例上,有效避免單個(gè)服務(wù)實(shí)例因負(fù)載過高而出現(xiàn)性能問題。假設(shè)商品服務(wù)有多個(gè)實(shí)例部署在不同的服務(wù)器上,Ribbon 就能根據(jù)一定的算法,比如隨機(jī)、輪詢等,將客戶端對(duì)商品服務(wù)的請(qǐng)求合理地分配到這些實(shí)例上,確保每個(gè)實(shí)例都能充分發(fā)揮作用,提高系統(tǒng)的整體性能和可用性。
還有 Hystrix 這個(gè)熔斷器組件,當(dāng)某個(gè)服務(wù)出現(xiàn)故障或者響應(yīng)超時(shí)的時(shí)候,它能快速熔斷,防止故障進(jìn)一步擴(kuò)散,就像電路中的保險(xiǎn)絲一樣,在電路過載時(shí)及時(shí)切斷電流,保護(hù)整個(gè)電路系統(tǒng)。比如在電商系統(tǒng)中,如果商品服務(wù)突然出現(xiàn)故障,Hystrix 會(huì)立即熔斷,避免訂單服務(wù)等其他服務(wù)一直等待商品服務(wù)的響應(yīng),從而保證整個(gè)系統(tǒng)的穩(wěn)定性,不至于因?yàn)橐粋€(gè)服務(wù)的故障而導(dǎo)致全線崩潰。
(二)MybatisPlus
MybatisPlus 是在 MyBatis 基礎(chǔ)上進(jìn)行增強(qiáng)的工具,它保留了 MyBatis 的靈活性,同時(shí)又提供了許多便捷的功能,大大提高了開發(fā)效率。
MybatisPlus 內(nèi)置了通用 Mapper,這意味著我們?cè)谶M(jìn)行數(shù)據(jù)庫(kù)操作時(shí),很多常見的增刪改查(CRUD)方法都無需手動(dòng)編寫 SQL 語句,只需要繼承通用 Mapper 接口,就可以直接使用這些現(xiàn)成的方法。例如,要查詢用戶表中的所有用戶信息,在 MybatisPlus 中,只需要在 Mapper 接口中繼承 BaseMapper 接口,然后在業(yè)務(wù)代碼中直接調(diào)用 selectList 方法即可,無需像傳統(tǒng) MyBatis 那樣編寫復(fù)雜的 SQL 語句和映射文件。
MybatisPlus 還提供了強(qiáng)大的分頁(yè)插件,使用起來非常簡(jiǎn)單。在實(shí)際應(yīng)用中,當(dāng)我們需要對(duì)大量數(shù)據(jù)進(jìn)行分頁(yè)展示時(shí),比如展示商品列表,每頁(yè)顯示 10 條數(shù)據(jù),只需要在查詢方法中傳入分頁(yè)參數(shù),MybatisPlus 就能自動(dòng)處理分頁(yè)邏輯,底層會(huì)根據(jù)不同的數(shù)據(jù)庫(kù)生成相應(yīng)的分頁(yè) SQL 語句,如 MySQL 的 LIMIT 語句,讓我們輕松實(shí)現(xiàn)數(shù)據(jù)的分頁(yè)查詢 ,而無需手動(dòng)編寫復(fù)雜的分頁(yè)代碼。
(三)MySQL 多數(shù)據(jù)源
多數(shù)據(jù)源,簡(jiǎn)單來說,就是在一個(gè)應(yīng)用程序中連接并使用多個(gè)數(shù)據(jù)庫(kù)。在實(shí)際業(yè)務(wù)場(chǎng)景中,有很多情況會(huì)用到多數(shù)據(jù)源。
讀寫分離是常見的場(chǎng)景之一。在一些數(shù)據(jù)讀寫頻繁的系統(tǒng)中,為了提高性能,我們通常會(huì)將讀操作和寫操作分離到不同的數(shù)據(jù)庫(kù)服務(wù)器上。比如一個(gè)新聞資訊網(wǎng)站,每天有大量的用戶讀取新聞內(nèi)容,但寫操作(如發(fā)布新新聞、更新新聞等)相對(duì)較少。這時(shí)就可以將讀操作指向從數(shù)據(jù)庫(kù),寫操作指向主數(shù)據(jù)庫(kù)。主數(shù)據(jù)庫(kù)負(fù)責(zé)數(shù)據(jù)的寫入和更新,保證數(shù)據(jù)的一致性;從數(shù)據(jù)庫(kù)則負(fù)責(zé)大量的讀操作,通過復(fù)制主數(shù)據(jù)庫(kù)的數(shù)據(jù)來提供查詢服務(wù)。這樣可以減輕主數(shù)據(jù)庫(kù)的壓力,提高系統(tǒng)的整體性能和響應(yīng)速度。
分庫(kù)分表也是多數(shù)據(jù)源的重要應(yīng)用場(chǎng)景。當(dāng)數(shù)據(jù)量非常龐大時(shí),單庫(kù)單表難以滿足存儲(chǔ)和性能的需求。例如,一個(gè)社交平臺(tái)擁有數(shù)億用戶,用戶表的數(shù)據(jù)量巨大,如果都存儲(chǔ)在一個(gè)數(shù)據(jù)庫(kù)的一張表中,查詢和更新操作都會(huì)變得非常緩慢。此時(shí)就可以按照一定的規(guī)則進(jìn)行分庫(kù)分表,比如按照用戶 ID 的哈希值將用戶數(shù)據(jù)分散存儲(chǔ)到多個(gè)數(shù)據(jù)庫(kù)的不同表中。這樣在進(jìn)行數(shù)據(jù)操作時(shí),就可以根據(jù)相應(yīng)的規(guī)則連接到不同的數(shù)據(jù)源,提高數(shù)據(jù)操作的效率和系統(tǒng)的可擴(kuò)展性。
三、集成與配置實(shí)戰(zhàn)
圖片
(一)引入依賴
首先,我們需要在項(xiàng)目的pom.xml文件中引入相關(guān)依賴。SpringCloud 集成 MybatisPlus 實(shí)現(xiàn) MySQL 多數(shù)據(jù)源配置,主要涉及以下依賴:
<dependencies><!-- SpringCloud相關(guān)依賴 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- MybatisPlus依賴 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>最新版本號(hào)</version></dependency><!-- MySQL驅(qū)動(dòng)依賴 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- 數(shù)據(jù)源相關(guān)依賴,這里以HikariCP為例 --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></dependency></dependencies>
SpringCloud 相關(guān)依賴,比如spring-cloud-starter-netflix-eureka-client,它用于實(shí)現(xiàn)服務(wù)的注冊(cè)與發(fā)現(xiàn),是 SpringCloud 微服務(wù)架構(gòu)中服務(wù)治理的重要組件。在一個(gè)分布式系統(tǒng)中,各個(gè)微服務(wù)通過 Eureka 進(jìn)行注冊(cè),這樣其他微服務(wù)就可以方便地發(fā)現(xiàn)和調(diào)用它們。
MybatisPlus 依賴mybatis-plus-boot-starter,它是 MybatisPlus 與 Spring Boot 集成的啟動(dòng)器,引入這個(gè)依賴后,我們就可以在 Spring Boot 項(xiàng)目中方便地使用 MybatisPlus 的各項(xiàng)功能,如通用 Mapper、分頁(yè)插件等。
MySQL 驅(qū)動(dòng)依賴mysql-connector-java,它是 Java 連接 MySQL 數(shù)據(jù)庫(kù)的橋梁,負(fù)責(zé)建立 Java 程序與 MySQL 數(shù)據(jù)庫(kù)之間的連接,讓我們能夠在 Java 代碼中執(zhí)行 SQL 語句,對(duì) MySQL 數(shù)據(jù)庫(kù)進(jìn)行各種操作。
數(shù)據(jù)源相關(guān)依賴,這里選用的 HikariCP 是一個(gè)高性能的數(shù)據(jù)源連接池。它能夠管理數(shù)據(jù)庫(kù)連接的創(chuàng)建、分配和釋放,提高數(shù)據(jù)庫(kù)連接的復(fù)用率,減少連接創(chuàng)建和銷毀的開銷,從而提升系統(tǒng)的性能和穩(wěn)定性。在多數(shù)據(jù)源配置中,不同的數(shù)據(jù)源都可以使用 HikariCP 來管理連接。
(二)配置多數(shù)據(jù)源
1. application.properties 配置
在src/main/resources目錄下的application.properties文件中,配置主從數(shù)據(jù)源的相關(guān)信息:
# 主數(shù)據(jù)源配置spring.datasource.master.url=jdbc:mysql://主數(shù)據(jù)庫(kù)地址:3306/主數(shù)據(jù)庫(kù)名?useUnicode=true&characterEncoding=utf-8&serverTimeznotallow=Asia/Shanghaispring.datasource.master.username=主數(shù)據(jù)庫(kù)用戶名spring.datasource.master.password=主數(shù)據(jù)庫(kù)密碼spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver# 從數(shù)據(jù)源配置spring.datasource.slave.url=jdbc:mysql://從數(shù)據(jù)庫(kù)地址:3306/從數(shù)據(jù)庫(kù)名?useUnicode=true&characterEncoding=utf-8&serverTimeznotallow=Asia/Shanghaispring.datasource.slave.username=從數(shù)據(jù)庫(kù)用戶名spring.datasource.slave.password=從數(shù)據(jù)庫(kù)密碼spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.url配置主數(shù)據(jù)源的連接 URL,包含了數(shù)據(jù)庫(kù)的地址、端口、數(shù)據(jù)庫(kù)名以及一些連接參數(shù)。useUnicode=true表示使用 Unicode 編碼,characterEncoding=utf-8指定字符編碼為 UTF-8,這樣可以確保數(shù)據(jù)庫(kù)能夠正確處理各種字符,避免亂碼問題;serverTimeznotallow=Asia/Shanghai設(shè)置服務(wù)器時(shí)區(qū)為上海時(shí)區(qū),保證時(shí)間相關(guān)的數(shù)據(jù)處理準(zhǔn)確無誤。
spring.datasource.master.username和spring.datasource.master.password分別配置主數(shù)據(jù)源的用戶名和密碼,用于連接數(shù)據(jù)庫(kù)時(shí)進(jìn)行身份驗(yàn)證。
spring.datasource.master.driver-class-name指定主數(shù)據(jù)源使用的 MySQL 驅(qū)動(dòng)類。
同理,從數(shù)據(jù)源的配置項(xiàng)spring.datasource.slave.url、spring.datasource.slave.username、spring.datasource.slave.password和spring.datasource.slave.driver-class-name的作用與主數(shù)據(jù)源類似,只是針對(duì)從數(shù)據(jù)源進(jìn)行配置。
2. 數(shù)據(jù)源配置類
創(chuàng)建數(shù)據(jù)源配置類,用于創(chuàng)建和管理數(shù)據(jù)源。在src/main/java/com/yourpackage/config目錄下創(chuàng)建DataSourceConfig.java文件:
import com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.SqlSessionTemplate;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;@Configuration@MapperScan(basePackages = "com.yourpackage.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory")public class DataSourceConfig {// 主數(shù)據(jù)源配置@Bean(name = "masterDataSource")@Primary@ConfigurationProperties("spring.datasource.master")public DataSource masterDataSource() {HikariConfig hikariConfig = new HikariConfig();hikariConfig.setJdbcUrl("spring.datasource.master.url");hikariConfig.setUsername("spring.datasource.master.username");hikariConfig.setPassword("spring.datasource.master.password");hikariConfig.setDriverClassName("spring.datasource.master.driver-class-name");return new HikariDataSource(hikariConfig);}// 主數(shù)據(jù)源的SqlSessionFactory@Bean(name = "masterSqlSessionFactory")@Primarypublic SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);// 可以在這里配置Mybatis的XML映射文件路徑等return bean.getObject();}// 主數(shù)據(jù)源的事務(wù)管理器@Bean(name = "masterTransactionManager")@Primarypublic DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}// 主數(shù)據(jù)源的SqlSessionTemplate@Bean(name = "masterSqlSessionTemplate")@Primarypublic SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}// 從數(shù)據(jù)源配置@Bean(name = "slaveDataSource")@ConfigurationProperties("spring.datasource.slave")public DataSource slaveDataSource() {HikariConfig hikariConfig = new HikariConfig();hikariConfig.setJdbcUrl("spring.datasource.slave.url");hikariConfig.setUsername("spring.datasource.slave.username");hikariConfig.setPassword("spring.datasource.slave.password");hikariConfig.setDriverClassName("spring.datasource.slave.driver-class-name");return new HikariDataSource(hikariConfig);}// 從數(shù)據(jù)源的SqlSessionFactory@Bean(name = "slaveSqlSessionFactory")public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);// 可以在這里配置Mybatis的XML映射文件路徑等return bean.getObject();}// 從數(shù)據(jù)源的事務(wù)管理器@Bean(name = "slaveTransactionManager")public DataSourceTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}// 從數(shù)據(jù)源的SqlSessionTemplate@Bean(name = "slaveSqlSessionTemplate")public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}}
在這個(gè)配置類中,我們使用了@Configuration注解,表示這是一個(gè)配置類。@MapperScan注解用于掃描指定包下的 Mapper 接口,basePackages指定了 Mapper 接口所在的包路徑,sqlSessionFactoryRef指定了對(duì)應(yīng)的 SqlSessionFactory。
@Bean注解用于創(chuàng)建 Bean 實(shí)例,我們分別創(chuàng)建了主數(shù)據(jù)源和從數(shù)據(jù)源的DataSource、SqlSessionFactory、DataSourceTransactionManager和SqlSessionTemplate。@Primary注解表示在有多個(gè)相同類型的 Bean 時(shí),優(yōu)先使用被標(biāo)記為@Primary的 Bean,這里主數(shù)據(jù)源相關(guān)的 Bean 都被標(biāo)記為@Primary,因?yàn)樵谝恍┠J(rèn)情況下,Spring 會(huì)優(yōu)先使用主數(shù)據(jù)源。
@ConfigurationProperties注解用于將application.properties文件中對(duì)應(yīng)前綴的配置項(xiàng)綁定到數(shù)據(jù)源配置中,比如spring.datasource.master前綴的配置項(xiàng)會(huì)綁定到主數(shù)據(jù)源的配置中。
(三)配置 MybatisPlus
1. 在 application.properties 中配置
在application.properties文件中添加 MybatisPlus 的相關(guān)配置:
# MybatisPlus Mapper文件路徑mybatis-plus.mapper-locatinotallow=classpath:/mapper/*.xml# 實(shí)體掃描路徑mybatis-plus.type-aliases-package=com.yourpackage.entity
mybatis-plus.mapper-locations配置了 MybatisPlus 的 Mapper XML 文件的路徑,classpath:/mapper/*.xml表示在src/main/resources/mapper目錄下的所有 XML 文件都會(huì)被加載。這些 XML 文件中定義了 SQL 語句與 Java 方法的映射關(guān)系,MybatisPlus 會(huì)根據(jù)這些配置來執(zhí)行數(shù)據(jù)庫(kù)操作。
mybatis-plus.type-aliases-package配置了實(shí)體類的掃描路徑,com.yourpackage.entity指定了實(shí)體類所在的包路徑。MybatisPlus 會(huì)自動(dòng)掃描這個(gè)包下的所有實(shí)體類,為它們創(chuàng)建別名,在 XML 文件中使用別名可以簡(jiǎn)化配置,提高代碼的可讀性。
2. MybatisPlus 配置類
如果有自定義的 MybatisPlus 配置,可以創(chuàng)建一個(gè)配置類。在src/main/java/com/yourpackage/config目錄下創(chuàng)建MybatisPlusConfig.java文件:
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分頁(yè)插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}}
在這個(gè)配置類中,我們創(chuàng)建了一個(gè)MybatisPlusInterceptor實(shí)例,并添加了PaginationInnerInterceptor分頁(yè)插件。這個(gè)分頁(yè)插件可以讓我們?cè)谑褂?MybatisPlus 進(jìn)行數(shù)據(jù)庫(kù)查詢時(shí),方便地實(shí)現(xiàn)分頁(yè)功能。通過配置類,我們可以對(duì) MybatisPlus 進(jìn)行更加靈活的自定義配置,滿足不同的業(yè)務(wù)需求。
四、測(cè)試與驗(yàn)證
圖片
(一)編寫測(cè)試代碼
為了驗(yàn)證多數(shù)據(jù)源配置是否成功,我們需要編寫一些測(cè)試代碼。首先,創(chuàng)建 Service 層接口和實(shí)現(xiàn)類,分別調(diào)用主從數(shù)據(jù)源進(jìn)行數(shù)據(jù)庫(kù)操作。
在src/main/java/com/yourpackage/service目錄下創(chuàng)建UserService.java接口:
import com.baomidou.mybatisplus.extension.service.IService;import com.yourpackage.entity.User;public interface UserService extends IService<User> {// 從主數(shù)據(jù)源查詢用戶User findUserFromMaster(Long id);// 從從數(shù)據(jù)源查詢用戶User findUserFromSlave(Long id);}
然后在src/main/java/com/yourpackage/service/impl目錄下創(chuàng)建UserServiceImpl.java實(shí)現(xiàn)類:
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.yourpackage.entity.User;import com.yourpackage.mapper.master.UserMasterMapper;import com.yourpackage.mapper.slave.UserSlaveMapper;import com.yourpackage.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl extends ServiceImpl<UserMasterMapper, User> implements UserService {@Autowiredprivate UserMasterMapper userMasterMapper;@Autowiredprivate UserSlaveMapper userSlaveMapper;@Overridepublic User findUserFromMaster(Long id) {return userMasterMapper.selectById(id);}@Overridepublic User findUserFromSlave(Long id) {return userSlaveMapper.selectById(id);}}
這里UserMasterMapper和UserSlaveMapper分別對(duì)應(yīng)主從數(shù)據(jù)源的 Mapper 接口,通過調(diào)用它們的方法來實(shí)現(xiàn)從不同數(shù)據(jù)源查詢用戶數(shù)據(jù)。
接著,創(chuàng)建 Controller 層來暴露接口,在src/main/java/com/yourpackage/controller目錄下創(chuàng)建UserController.java:
import com.yourpackage.entity.User;import com.yourpackage.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class UserController {@Autowiredprivate UserService userService;@GetMapping("/user/master/{id}")public User getUserFromMaster(@PathVariable Long id) {return userService.findUserFromMaster(id);}@GetMapping("/user/slave/{id}")public User getUserFromSlave(@PathVariable Long id) {return userService.findUserFromSlave(id);}}
在這個(gè) Controller 中,定義了兩個(gè)接口/user/master/{id}和/user/slave/{id},分別用于從主數(shù)據(jù)源和從數(shù)據(jù)源查詢用戶信息。
(二)啟動(dòng)測(cè)試
完成測(cè)試代碼編寫后,啟動(dòng) SpringCloud 應(yīng)用。確保主從數(shù)據(jù)庫(kù)都已正常運(yùn)行,并且數(shù)據(jù)庫(kù)中存在相應(yīng)的測(cè)試數(shù)據(jù)。
啟動(dòng)應(yīng)用后,可以使用工具如 Postman 來進(jìn)行接口測(cè)試。
當(dāng)訪問http://localhost:8080/user/master/1時(shí),Postman 會(huì)向該接口發(fā)送 GET 請(qǐng)求,SpringCloud 應(yīng)用接收到請(qǐng)求后,會(huì)調(diào)用UserServiceImpl中的findUserFromMaster方法,該方法通過UserMasterMapper從主數(shù)據(jù)源查詢 ID 為 1 的用戶信息,并將結(jié)果返回給 Postman。
同樣,當(dāng)訪問http://localhost:8080/user/slave/1時(shí),會(huì)調(diào)用findUserFromSlave方法,從從數(shù)據(jù)源查詢用戶信息。
如果在 Postman 中能夠正確獲取到來自不同數(shù)據(jù)源的用戶數(shù)據(jù),說明多數(shù)據(jù)源配置成功。例如,從主數(shù)據(jù)源查詢到的用戶數(shù)據(jù)可能是{"id":1,"name":"張三","age":20},從從數(shù)據(jù)源查詢到的用戶數(shù)據(jù)可能是{"id":1,"name":"李四","age":25} ,這就表明我們成功實(shí)現(xiàn)了 SpringCloud 集成 MybatisPlus 的 MySQL 多數(shù)據(jù)源配置,并且能夠在不同數(shù)據(jù)源之間進(jìn)行正確的數(shù)據(jù)操作。
五、常見問題及解決方法
圖片
(一)依賴沖突問題
在引入 SpringCloud、MybatisPlus 和 MySQL 相關(guān)依賴時(shí),可能會(huì)出現(xiàn)依賴沖突的情況。比如,不同版本的依賴可能存在兼容性問題。例如,MybatisPlus 的某個(gè)版本可能與 SpringCloud 的某個(gè)版本不兼容,導(dǎo)致項(xiàng)目啟動(dòng)失敗或者出現(xiàn)奇怪的運(yùn)行時(shí)錯(cuò)誤。
要排查依賴沖突,可以使用 Maven 的dependency:tree命令,它會(huì)以樹形結(jié)構(gòu)展示項(xiàng)目中所有依賴及其版本信息。通過查看這個(gè)依賴樹,我們可以發(fā)現(xiàn)是否存在同一個(gè)依賴的不同版本被引入的情況。例如,如果在依賴樹中看到mybatis-plus-boot-starter同時(shí)存在 3.4.0 和 3.5.0 兩個(gè)版本,就可能存在沖突風(fēng)險(xiǎn)。
解決依賴沖突的方法有多種。一種是在pom.xml文件中明確指定依賴的版本,確保所有相關(guān)依賴使用兼容的版本。比如,如果確定 MybatisPlus 的 3.4.0 版本與當(dāng)前 SpringCloud 版本兼容,就在pom.xml中固定mybatis-plus-boot-starter的版本為 3.4.0:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency>
另一種方法是使用exclusions標(biāo)簽排除不需要的依賴。例如,如果某個(gè)依賴引入了一個(gè)與項(xiàng)目中其他依賴沖突的子依賴,可以通過exclusions將其排除:
<dependency><groupId>某個(gè)groupId</groupId><artifactId>某個(gè)artifactId</artifactId><exclusions><exclusion><groupId>沖突依賴的groupId</groupId><artifactId>沖突依賴的artifactId</artifactId></exclusion></exclusions></dependency>
(二)數(shù)據(jù)源配置錯(cuò)誤
數(shù)據(jù)源配置錯(cuò)誤是多數(shù)據(jù)源配置中常見的問題之一。比如,在application.properties文件中配置數(shù)據(jù)源信息時(shí),如果數(shù)據(jù)庫(kù)的 URL、用戶名、密碼等信息填寫錯(cuò)誤,就會(huì)導(dǎo)致無法連接數(shù)據(jù)庫(kù)。例如,將數(shù)據(jù)庫(kù) URL 中的端口號(hào)寫錯(cuò),原本應(yīng)該是3306,寫成了3307,這樣在項(xiàng)目啟動(dòng)時(shí)就會(huì)報(bào)錯(cuò),提示無法連接到指定的數(shù)據(jù)庫(kù)地址。
為了檢查數(shù)據(jù)源配置是否正確,可以先手動(dòng)使用數(shù)據(jù)庫(kù)客戶端工具,如 Navicat,嘗試連接數(shù)據(jù)庫(kù)。如果能正常連接,說明數(shù)據(jù)庫(kù)本身沒有問題,問題可能出在項(xiàng)目的配置上。在項(xiàng)目中,可以查看啟動(dòng)日志,通常會(huì)有詳細(xì)的錯(cuò)誤信息提示。例如,日志中可能會(huì)出現(xiàn)Cannot resolve host '錯(cuò)誤的數(shù)據(jù)庫(kù)地址'這樣的錯(cuò)誤信息,這就表明數(shù)據(jù)庫(kù)地址配置有誤。
修正配置時(shí),要仔細(xì)核對(duì)application.properties文件中的各項(xiàng)配置信息,確保與數(shù)據(jù)庫(kù)實(shí)際的連接信息一致。同時(shí),還要注意配置的格式是否正確,比如 URL 中的參數(shù)分隔符是否正確使用了&,用戶名和密碼是否有多余的空格等。
(三)MybatisPlus 映射問題
在使用 MybatisPlus 時(shí),可能會(huì)遇到映射文件找不到或映射錯(cuò)誤的情況。如果在配置文件中指定的映射文件路徑不正確,比如mybatis-plus.mapper-locatinotallow=classpath:/mapper/*.xml,而實(shí)際的映射文件存放在src/main/resources/mapper/user目錄下,就會(huì)導(dǎo)致找不到映射文件,從而在執(zhí)行數(shù)據(jù)庫(kù)操作時(shí)出現(xiàn)Invalid bound statement (not found)的錯(cuò)誤。
另外,映射文件的命名規(guī)范也很重要。映射文件的命名通常要與 Mapper 接口的名稱相對(duì)應(yīng),并且要放在正確的目錄下。例如,UserMapper接口對(duì)應(yīng)的映射文件應(yīng)該命名為UserMapper.xml,并且要放在mapper目錄下與UserMapper接口相對(duì)應(yīng)的子目錄中。
為了解決映射問題,首先要檢查配置文件中mybatis-plus.mapper-locations指定的路徑是否正確。如果映射文件有多層目錄結(jié)構(gòu),要確保路徑能夠正確匹配到所有的映射文件。比如,如果映射文件存放在src/main/resources/mapper/user目錄下,配置路徑可以寫成mybatis-plus.mapper-locatinotallow=classpath:/mapper/user/*.xml。
其次,要檢查映射文件的命名是否符合規(guī)范,并且要確保映射文件中的 SQL 語句與 Mapper 接口中的方法簽名一致。例如,Mapper 接口中有一個(gè)selectUserById方法,那么在映射文件中就應(yīng)該有對(duì)應(yīng)的<select id="selectUserById">標(biāo)簽,并且 SQL 語句的邏輯要正確實(shí)現(xiàn)根據(jù) ID 查詢用戶的功能。
六、總結(jié)與展望
圖片
在今天的分享中,我們成功地在 SpringCloud 微服務(wù)架構(gòu)中集成了 MybatisPlus,并實(shí)現(xiàn)了 MySQL 多數(shù)據(jù)源配置?;仡櫿麄€(gè)過程,我們首先引入了 SpringCloud、MybatisPlus、MySQL 驅(qū)動(dòng)以及數(shù)據(jù)源相關(guān)的依賴,這些依賴是整個(gè)配置的基礎(chǔ),它們相互協(xié)作,為我們實(shí)現(xiàn)多數(shù)據(jù)源配置提供了必要的功能支持。
接著,在application.properties文件中配置了主從數(shù)據(jù)源的連接信息,包括 URL、用戶名、密碼和驅(qū)動(dòng)類名等。同時(shí),創(chuàng)建了數(shù)據(jù)源配置類,在其中定義了主從數(shù)據(jù)源的DataSource、SqlSessionFactory、DataSourceTransactionManager和SqlSessionTemplate等 Bean,通過這些配置,我們實(shí)現(xiàn)了對(duì)不同數(shù)據(jù)源的連接和管理。
在配置 MybatisPlus 時(shí),我們?cè)赼pplication.properties文件中指定了 Mapper 文件路徑和實(shí)體掃描路徑,還創(chuàng)建了 MybatisPlus 配置類,添加了分頁(yè)插件等自定義配置,讓 MybatisPlus 能夠更好地滿足我們的業(yè)務(wù)需求。
為了驗(yàn)證配置的正確性,我們編寫了測(cè)試代碼,包括 Service 層接口和實(shí)現(xiàn)類,以及 Controller 層接口。通過啟動(dòng)應(yīng)用并使用 Postman 進(jìn)行接口測(cè)試,我們成功地從主從數(shù)據(jù)源獲取到了數(shù)據(jù),這表明我們的多數(shù)據(jù)源配置是有效的。
在這個(gè)過程中,我們也遇到了一些常見問題,如依賴沖突、數(shù)據(jù)源配置錯(cuò)誤和 MybatisPlus 映射問題等。通過使用 Maven 的dependency:tree命令排查依賴沖突,手動(dòng)使用數(shù)據(jù)庫(kù)客戶端工具檢查數(shù)據(jù)源配置,以及仔細(xì)核對(duì)映射文件路徑和命名規(guī)范等方法,我們成功地解決了這些問題。
展望未來,隨著分布式系統(tǒng)的不斷發(fā)展,數(shù)據(jù)處理的需求也會(huì)越來越復(fù)雜。在多數(shù)據(jù)源配置方面,可能會(huì)出現(xiàn)更多類型的數(shù)據(jù)源需要集成,如 NoSQL 數(shù)據(jù)庫(kù)、分布式文件系統(tǒng)等。同時(shí),對(duì)于數(shù)據(jù)的一致性、安全性和性能優(yōu)化等方面的要求也會(huì)越來越高。我們需要不斷學(xué)習(xí)和探索新的技術(shù)和方法,以適應(yīng)這些發(fā)展趨勢(shì)。例如,關(guān)注新型存儲(chǔ)技術(shù)、人工智能與機(jī)器學(xué)習(xí)在數(shù)據(jù)處理中的應(yīng)用,以及分布式數(shù)據(jù)庫(kù)的跨云和多云部署等技術(shù),為分布式系統(tǒng)的數(shù)據(jù)處理提供更高效、更可靠的解決方案。希望今天的分享能對(duì)大家在 SpringCloud 集成 MybatisPlus 實(shí)現(xiàn) MySQL 多數(shù)據(jù)源配置方面有所幫助,也期待大家在未來的開發(fā)中不斷探索和創(chuàng)新。