目錄java
tags: multi-datasource java springbootmysql
一句話歸納:Spring Boot開發中鏈接多個數據庫進行讀寫操做,使用多套數據源是最直接、簡單的方式。git
在開發過程當中,避免不了須要同時操做多個數據庫的狀況,一般的應用場景以下 :github
使用 Spring Boot 該如何處理多個數據庫的讀寫,通常有如下幾種策略:web
本系列文章「搞定SpringBoot多數據源」將針對以上幾個策略進行描述,本文是第一篇:「多套數據源」,主要以主從場景爲實例,結合代碼,對多套數據源的實現進行描述,內容包括搭建 Spring Boot + MyBatis Plus 工程、多數據源配置、多數據源處理與使用邏輯。spring
本文所涉及到的示例代碼:https://github.com/mianshenglee/my-example/tree/master/multi-datasource
,讀者可結合一塊兒看。sql
JDK1.8
2.2.2.RELEASE
3.3.0
IDEA
3.3.9
5.6.26
1.18.10
多套數據源,顧名思義每個數據庫有一套獨立的操做。從下往上,數據庫、會話工廠、DAO操做,服務層都是獨立的一套,以下所示:數據庫
本示例中,以一主一從兩個數據庫,兩數據庫的分別有一個表 test_user
,表結構一致,爲便於說明,兩個表中的數據是不同的。兩個表結構可在示例代碼中的 sql
目錄中獲取。apache
使用 spring.io構建初始 Spring Boot 工程,選用如下幾個構件:後端
MyBatis Plus 是對 MyBatis 加強,簡化 DAO 操做,提升數據庫操做效率。依賴以下:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.0</version> </dependency>
主要添加如下幾個包:
├─config ---------------------------------- // 數據源配置 ├─controller ------------------------------ // web服務 ├─entity ---------------------------------- // 實體類 │ ├─master │ └─slave ├─mapper ---------------------------------- // dao操做類 │ ├─master │ └─slave └─vo -------------------------------------- // 視圖返回對象
注:
- 因爲示例簡單,省略service層
- 實體類及mapper均根據主從進行劃分
Spring Boot 的默認配置文件是 application.properties
,因爲有兩個數據庫配置,獨立配置數據庫是好的實踐,所以添加配置文件 jbdc.properties
,添加如下自定義的主從數據庫配置:
# master spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/mytest?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8 spring.datasource.master.username=root spring.datasource.master.password=111111 # slave spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.slave.jdbc-url=jdbc:mysql://localhost:3306/my_test1?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8 spring.datasource.slave.username=root spring.datasource.slave.password=111111
有了數據源鏈接信息,須要把數據源注入到 Spring 中。因爲每一個數據庫使用獨立的一套數據庫鏈接,數據庫鏈接使用的 SqlSession
進行會話鏈接,SqlSession
是由SqlSessionFactory
生成。所以,須要分別配置SqlSessionFactory
。如下操做均在 config
目錄 下:
(1)添加 DataSourceConfig
配置文件,注入主從數據源
@Configuration @PropertySource("classpath:config/jdbc.properties") public class DatasourceConfig { @Bean("master") @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource masterDataSource(){ return DataSourceBuilder.create().build(); } @Bean("slave") @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaveDataSource(){ return DataSourceBuilder.create().build(); } }
- 註解
PropertySource
指定配置信息文件- 註解
ConfigurationProperties
指定主從配置前綴- 分別指定主從數據源的 bean 名稱爲
master
,slave
(2)添加 MasterMybatisConfig
配置文件,注入 Master 的SqlSessionFactory
@Configuration @MapperScan(basePackages = "me.mason.demo.basicmultidatasource.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory") public class MasterMybatisConfig { /** * 注意,此處須要使用MybatisSqlSessionFactoryBean,不是SqlSessionFactoryBean, * 不然,使用mybatis-plus的內置函數時就會報invalid bound statement (not found)異常 */ @Bean("masterSqlSessionFactory") public SqlSessionFactory masterSqlSessionFactory(@Qualifier("master") DataSource dataSource) throws Exception { // 設置數據源 MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); mybatisSqlSessionFactoryBean.setDataSource(dataSource); //mapper的xml文件位置 PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); String locationPattern = "classpath*:/mapper/master/*.xml"; mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern)); //對應數據庫的entity位置 String typeAliasesPackage = "me.mason.demo.basicmultidatasource.entity.master"; mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage); return mybatisSqlSessionFactoryBean.getObject(); } }
- 註解
MapperScan
指定那些包下的mapper
使用本數據源,並指定使用哪一個SqlSessionFactory
,注意,此處的sqlSessionFactoryRef
即本配置中的注入的SqlSessionFactory
。- 設置指定的數據源,此處是名爲
master
的數據源,使用Qualifier
指定。- MyBatis Plus 對應的 Mapper 如有自定義的 mapper.xml, 則使用
setMapperLocations
指定。- 若須要對實體進行別名處理,則使用
setTypeAliasesPackage
指定。
(3)添加 SlaveMybatisConfig
配置文件,注入Slave 的 SqlSessionFactory
與(2)一致,把 master 改成 slave便可。
在 MyBatis 配置中,實體設置 typeAliases
能夠簡化 xml 的配置,前面提到,使用 typeAliasesPackage
設置實體路徑,在 entity
包下分別設置 master
和 slave
包,存放兩個庫對應的表實體,使用 Lombok 簡化實體操做。以下:
@Data @TableName("test_user") public class MasterTestUser implements Serializable { private static final long serialVersionUID = 1L; /** id */ private Long id; /** 姓名 */ private String name; ... }
在 mapper
包下,分別添加 master
和 slave
包,存放兩個庫對應的 Mapper ,因爲 MyBatis Plus 自己已包含基本的 CRUD 操做,因此不少時候能夠不用 xml 文件配置。若須要自定義操做,須要結合 xml文件,與此同時須要指定對應的 xml 文件所在目錄。以下:
@Repository public interface MasterTestUserMapper extends BaseMapper<MasterTestUser> { /** * 自定義查詢 * @param wrapper 條件構造器 */ List<MasterTestUser> selectAll(@Param(Constants.WRAPPER)Wrapper<MasterTestUser> wrapper); }
slave對應的Mapper與此相似
MyBatis Plus 的默認mapper xml 文件路徑爲 classpath*:/mapper/**/*.xml
,即 resources/mapper
下,一樣設置 master
及 slave
目錄,分別存放對應的mapper xml 文件。如下是 master 的自定義操做:
<mapper namespace="me.mason.demo.basicmultidatasource.mapper.master.MasterTestUserMapper"> <select id="selectAll" resultType="masterTestUser"> select * from test_user <if test="ew!=null"> ${ew.customSqlSegment} </if> </select> </mapper>
通過上面的多套數據源配置,可知道,若須要操做哪一個數據庫,直接使用對應的 mapper 進行 CRUD 操做便可。以下爲 Controller 中分別查詢兩個庫,獲取到的數據合在一塊兒返回:
@RestController @RequestMapping("/user") public class TestUserController { @Autowired private MasterTestUserMapper masterTestUserMapper; @Autowired private SlaveTestUserMapper slaveTestUserMapper; /** * 查詢所有 */ @GetMapping("/listall") public Object listAll() { //master庫,自定義接口查詢 QueryWrapper<MasterTestUser> queryWrapper = new QueryWrapper<>(); List<MasterTestUser> resultData = masterTestUserMapper.selectAll(queryWrapper.isNotNull("name")); //slave庫,mp內置接口 List<SlaveTestUser> resultDataSlave = slaveTestUserMapper.selectList(null); //返回 Map<String, Object> result = new HashMap<>(); result.put("master" , resultData); result.put("slave" , resultDataSlave); return ResponseResult.success(result); } }
- 使用Autowired註解注入對應的mapper
- 使用對應數據庫的 mapper 進行業務操做
- 根據業務在數據庫中執行相應的操做,如主只作增刪改操做、從只讀操做
至此,多數據源的實現已完成,當前示例是兩個同構的數據庫,固然,如果異構的數據庫,或者多於兩個的數據庫,處理方式是同樣的,只不過是把數據源增長一套而已。
由上述說明,咱們能夠總結一下使用多套數據源的方法進行多數據庫操做,它的優缺點是什麼。
SqlSessionFactory
是一個工廠,建議是使用單例,徹底能夠重用,不須要創建多個,只須要更改數據源便可,跟多線程,使用線程池減小資源消耗是同一道理。正由於有上述的缺點,因此還有改進的空間。因而就有了動態數據源,至於動態數據源如何實現,下回分解。
本文對多個數據庫的操做進行了初步探討,並對使用多套源的策略進行講解,結合主從代碼示例,搭建了 Spring Boot + MyBatis Plus 工程,配置多數據源及使用 Mapper 進行多數據源操做,最後對多套數據源的優缺點進行總結。但願小夥伴們能夠對多數據源操做有個初步印象。
本文有配套的示例代碼,有興趣的能夠跑一下示例來感覺一下。
https://www.liaoxuefeng.com/article/1182502273240832
https://juejin.im/post/5b790a866fb9a019ea01f38c
https://juejin.im/post/5cb0023d5188250df17d4ffc
https://juejin.im/post/5a927d23f265da4e7e10d740
個人公衆號(搜索Mason技術記錄
),獲取更多技術記錄: