SpringBoot集成Sharding-JDBC實(shí)現(xiàn)分庫分表方式
一、環(huán)境搭建
1.創(chuàng)建一個(gè)springboot項(xiàng)目,引入以下依賴。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.20</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
2.創(chuàng)建一個(gè)數(shù)據(jù)庫user和兩張表user_1,user_2
CREATE DATABASE `user`; CREATE TABLE `user_1` ( `id` bigint(30) NOT NULL, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CREATE TABLE `user_2` ( `id` bigint(30) NOT NULL, `username` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
3.分別創(chuàng)建user表對應(yīng)的實(shí)體類和mapper
實(shí)體類代碼
@Data public class User { private Long id; private String username; private String password; private String gender; }
mapper代碼
public interface UserMapper extends BaseMapper<User>{ }
結(jié)構(gòu)圖:
二、實(shí)現(xiàn)水平分表
需求:現(xiàn)在有兩個(gè)user表,一個(gè)是user_1,一個(gè)是user_2,當(dāng)id為偶數(shù)的時(shí)候向user_1表中插入數(shù)據(jù),當(dāng)id為奇數(shù)的時(shí)候向user_2表中插入數(shù)據(jù),實(shí)現(xiàn)水平分表。
1.配置application.properties
#指定當(dāng)前應(yīng)用的所有數(shù)據(jù)源標(biāo)識(由于后期可能會涉及到多個(gè)數(shù)據(jù)源,或讀寫分離等,這里要為每個(gè)數(shù)據(jù)源 # 起一個(gè)標(biāo)識名,然后為每個(gè)數(shù)據(jù)源具體配置) spring.shardingsphere.datasource.names=d1 #配置d1這個(gè)數(shù)據(jù)源,由于這里是水平分表,所以只需要一個(gè)數(shù)據(jù)源即可 其中d1代表該數(shù)據(jù)源的一個(gè)標(biāo)識 spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅(qū)動(dòng) spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d1.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d1.password=root #由于是水平分表,所以會涉及到多張相同的表,這里指定這些表的分布情況:在哪個(gè)數(shù)據(jù)源上,以及一共有幾張表 #指定在d1數(shù)據(jù)源,且有user_1和user_2兩張表 #$->{1..2}該表達(dá)式是與前面的user_相拼接的,不能亂寫,例如我們現(xiàn)在的兩張表名是user_1和user_2,那這里就是user_$->{1..2} #如果我們分布了3張表 user_5,user_6,user_7,那這里就是user_$->{5..6..7} spring.shardingsphere.sharding.tables.user.actual-data-nodes=d1.user_$->{1..2} # 指定 user 表里面主鍵id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成該id spring.shardingsphere.sharding.tables.user.key-generator.column=id spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE # 指定分片策略 約定 id 值偶數(shù)添加到 user_1 表,如果 id 是奇數(shù)添加到 user_2表 #指定要根據(jù)哪個(gè)字段進(jìn)行分表,這里根據(jù)id進(jìn)行分表 spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id #執(zhí)行分表的規(guī)則:注意這里是$->{id% 2 + 1},由于偶數(shù)%2的結(jié)果為0,但是我們并沒有user_0這樣表 #所以我們要在取模的結(jié)果上+1 這樣就實(shí)現(xiàn)了如果是偶數(shù)那么取模的結(jié)果就是user_1,如果是奇數(shù)就是user_2 spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1} #開啟sql 輸出日志 spring.shardingsphere.props.sql.show=true # 由于一個(gè)實(shí)體類對應(yīng)兩張表,所以會產(chǎn)生覆蓋操作,加上這個(gè)配置解決覆蓋問題 spring.main.allow-bean-definition-overriding=true
2.編寫測試代碼
@Test void testAddUser() { for (int i = 0;i < 6;i++){ User user = new User(); user.setGender("0"); user.setPassword(UUID.randomUUID().toString().substring(0,5)); user.setUsername("-->" + i); userMapper.insert(user); } }
3.日志查看:
可以看到當(dāng)user_id的值為偶數(shù)的時(shí)候,是向user_1表中插入的。
再看當(dāng)user_id的值為奇數(shù)的時(shí)候,該條數(shù)據(jù)插入了user_2這個(gè)表。
三、實(shí)現(xiàn)水平分庫
需求:現(xiàn)在有兩個(gè)user庫,一個(gè)是user_db1,一個(gè)是user_db2,每個(gè)user庫中都有兩張相同的表,user_1,user_2,當(dāng)user對象的gender屬性值為1的時(shí)候向user_db1庫中插入,當(dāng)user對象的gender屬性值為0的時(shí)候向user_db2庫中插入,這是分庫的規(guī)則,分表的規(guī)則是,當(dāng)id為偶數(shù)的時(shí)候向user_1表中插入數(shù)據(jù),當(dāng)id為奇數(shù)的時(shí)候向user_2表中插入數(shù)據(jù)。(建表語句和上面是相同的)
結(jié)構(gòu)如下:
2.配置application.properties
#指定當(dāng)前應(yīng)用的所有數(shù)據(jù)源標(biāo)識(由于后期可能會涉及到多個(gè)數(shù)據(jù)源,或讀寫分離等,這里要為每個(gè)數(shù)據(jù)源 # 起一個(gè)標(biāo)識名,然后為每個(gè)數(shù)據(jù)源具體配置) spring.shardingsphere.datasource.names=d1,d2 #配置d1這個(gè)數(shù)據(jù)源,由于這里是水平分表,所以只需要一個(gè)數(shù)據(jù)源即可 其中d1代表該數(shù)據(jù)源的一個(gè)標(biāo)識 spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅(qū)動(dòng) spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user_db1?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d1.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d1.password=root #由于是兩個(gè)數(shù)據(jù)庫,所以要配置兩個(gè)數(shù)據(jù)源 #配置d2數(shù)據(jù)源 spring.shardingsphere.datasource.d2.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅(qū)動(dòng) spring.shardingsphere.datasource.d2.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d2.url=jdbc:mysql://localhost:3308/user_db2?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d2.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d2.password=root #指定數(shù)據(jù)庫和表的分布情況 #指定數(shù)據(jù)庫分布情況,數(shù)據(jù)庫里面表分布情況 #d$->{1..2}.user_$->{1..2} 表示在d1,d2數(shù)據(jù)源上都有user_1和user_2兩張表 spring.shardingsphere.sharding.tables.user.actual-data-nodes=d$->{1..2}.user_$->{1..2} # 指定 user 表里面主鍵id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成該id spring.shardingsphere.sharding.tables.user.key-generator.column=id spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE # 指定分片策略 約定 id 值偶數(shù)添加到 user_1 表,如果 id 是奇數(shù)添加到 user_2表 #指定要根據(jù)哪個(gè)字段進(jìn)行分表,這里根據(jù)id進(jìn)行分表 spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id #執(zhí)行分表的規(guī)則:注意這里是$->{id% 2 + 1},由于偶數(shù)%2的結(jié)果為0,但是我們并沒有user_0這樣表 #所以我們要在取模的結(jié)果上+1 這樣就實(shí)現(xiàn)了如果是偶數(shù)那么取模的結(jié)果就是user_1,如果是奇數(shù)就是user_2 spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1} #============================================================================================ #以上指定了分表策略,下面指定分庫策略,也就是gender為0則向user_db1中插入,為1則向user_db2中插入 spring.shardingsphere.sharding.tables.user.database-strategy.inline..sharding-column=gender #如果gender為0 則表達(dá)式{gender=='0'?1:2}的結(jié)果就是1,則d$->{gender=='0'?1:2} = d1,就會向d1數(shù)據(jù)源也就是user_db1庫中添加 #如果gender為1 則表達(dá)式{gender=='0'?1:2}的結(jié)果就是2,則d$->{gender=='0'?1:2} = d2,就會向d1數(shù)據(jù)源也就是user_db2庫中添加 spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=d$->{gender=='0'?1:2} #開啟sql 輸出日志 spring.shardingsphere.props.sql.show=true # 由于一個(gè)實(shí)體類對應(yīng)兩張表,所以會產(chǎn)生覆蓋操作,加上這個(gè)配置解決覆蓋問題 spring.main.allow-bean-definition-overriding=true
2.編寫測試代碼
@Test void testAddUser() { for (int i = 0;i < 10;i++){ User user = new User(); user.setPassword(UUID.randomUUID().toString().substring(0,5)); user.setUsername("-->" + i); if (i % 2 == 0) user.setGender("0"); else user.setGender("1"); userMapper.insert(user); } }
3.數(shù)據(jù)庫查看
可以看到:gender為0,且id為偶數(shù)插入到了user_db1庫中的,user_1表。
可以看到:gender為0,且id為奇數(shù)插入到了user_db1庫中的,user_2表。
可以看到:gender為1,且id為偶數(shù)插入到了user_db2庫中的,user_1表。
可以看到:gender為1,且id為奇數(shù)插入到了user_db2庫中的,user_2表。
四、公共表的配置
有些表的數(shù)據(jù)量不大,需要在每個(gè)數(shù)據(jù)庫中都有,這時(shí)需要配置公共表。
向user_db1,和user_db2兩個(gè)數(shù)據(jù)庫都創(chuàng)建一個(gè)t_dict表
CREATE table t_dicit( id BIGINT(30) PRIMARY key, `dstatus` VARCHAR(255) not null, `description` VARCHAR(255) not null )
status和desc是mysql的兩個(gè)關(guān)鍵字,表的字段名盡量避開這些關(guān)鍵字,否則會發(fā)生運(yùn)行時(shí)異常。
1.配置application.properties
#指定當(dāng)前應(yīng)用的所有數(shù)據(jù)源標(biāo)識(由于后期可能會涉及到多個(gè)數(shù)據(jù)源,或讀寫分離等,這里要為每個(gè)數(shù)據(jù)源 # 起一個(gè)標(biāo)識名,然后為每個(gè)數(shù)據(jù)源具體配置) spring.shardingsphere.datasource.names=d1,d2 #配置d1這個(gè)數(shù)據(jù)源,由于這里是水平分表,所以只需要一個(gè)數(shù)據(jù)源即可 其中d1代表該數(shù)據(jù)源的一個(gè)標(biāo)識 spring.shardingsphere.datasource.d1.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅(qū)動(dòng) spring.shardingsphere.datasource.d1.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d1.url=jdbc:mysql://localhost:3308/user_db1?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d1.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d1.password=root #由于是兩個(gè)數(shù)據(jù)庫,所以要配置兩個(gè)數(shù)據(jù)源 #配置d2數(shù)據(jù)源 spring.shardingsphere.datasource.d2.type=com.alibaba.druid.pool.DruidDataSource #指定鏈接驅(qū)動(dòng) spring.shardingsphere.datasource.d2.driver-class-name=com.mysql.cj.jdbc.Driver #指定鏈接url spring.shardingsphere.datasource.d2.url=jdbc:mysql://localhost:3308/user_db2?useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC #指定鏈接用戶名 spring.shardingsphere.datasource.d2.username=root #指定鏈接密碼 spring.shardingsphere.datasource.d2.password=root #指定數(shù)據(jù)庫和表的分布情況 #指定數(shù)據(jù)庫分布情況,數(shù)據(jù)庫里面表分布情況 #d$->{1..2}.user_$->{1..2} 表示在d1,d2數(shù)據(jù)源上都有user_1和user_2兩張表 spring.shardingsphere.sharding.tables.user.actual-data-nodes=d$->{1..2}.user_$->{1..2} # 指定 user 表里面主鍵id 以及id的生成策略 SNOWFLAKE:表示用雪花算法生成該id spring.shardingsphere.sharding.tables.user.key-generator.column=id spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE # 指定分片策略 約定 id 值偶數(shù)添加到 user_1 表,如果 id 是奇數(shù)添加到 user_2表 #指定要根據(jù)哪個(gè)字段進(jìn)行分表,這里根據(jù)id進(jìn)行分表 spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=id #執(zhí)行分表的規(guī)則:注意這里是$->{id% 2 + 1},由于偶數(shù)%2的結(jié)果為0,但是我們并沒有user_0這樣表 #所以我們要在取模的結(jié)果上+1 這樣就實(shí)現(xiàn)了如果是偶數(shù)那么取模的結(jié)果就是user_1,如果是奇數(shù)就是user_2 spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{id% 2 + 1} #============================================================================================ #以上指定了分表策略,下面指定分庫策略,也就是gender為0則向user_db1中插入,為1則向user_db2中插入 spring.shardingsphere.sharding.tables.user.database-strategy.inline..sharding-column=gender #如果gender為0 則表達(dá)式{gender=='0'?1:2}的結(jié)果就是1,則d$->{gender=='0'?1:2} = d1,就會向d1數(shù)據(jù)源也就是user_db1庫中添加 #如果gender為1 則表達(dá)式{gender=='0'?1:2}的結(jié)果就是2,則d$->{gender=='0'?1:2} = d2,就會向d1數(shù)據(jù)源也就是user_db2庫中添加 spring.shardingsphere.sharding.tables.user.database-strategy.inline.algorithm-expression=d$->{gender=='0'?1:2} #============================================================================================ #配置公共表 在向t_dicit表插入數(shù)據(jù)時(shí) 這些默認(rèn)的數(shù)據(jù)源(d1,d2)的t_dicit表都會插入該數(shù)據(jù) spring.shardingsphere.sharding.broadcast-tables=t_dicit spring.shardingsphere.sharding.tables.t_dicit.key-generator.column=id spring.shardingsphere.sharding.tables.t_dicit.key-generator.type=SNOWFLAKE #開啟sql 輸出日志 spring.shardingsphere.props.sql.show=true # 由于一個(gè)實(shí)體類對應(yīng)兩張表,所以會產(chǎn)生覆蓋操作,加上這個(gè)配置解決覆蓋問題 spring.main.allow-bean-definition-overriding=true
2.編寫實(shí)體類和mapper
@TableName("t_dicit") @Data public class Dict { @TableId private Long id; private String dstatus; private String description; }
public interface DictMapper extends BaseMapper<Dict> { }
3.編寫測試程序
@Test public void testDict(){ Dict dict = new Dict(); dict.setDescription("啟用狀態(tài)"); dict.setDstatus("A"); dictMapper.insert(dict); }
4.查看日志發(fā)現(xiàn)分別向兩個(gè)數(shù)據(jù)源發(fā)送了sql
5.查看表
兩個(gè)庫的t_dicit表都有了該數(shù)據(jù)。
同樣如果是刪除公共表的數(shù)據(jù)也是同時(shí)將兩個(gè)數(shù)據(jù)庫中的記錄刪除。
@Test public void testDictDel(){ dictMapper.deleteById(1270356973266165762L); }
運(yùn)行日志:
兩個(gè)庫中的數(shù)據(jù)都被刪除。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot+MybatisPlus實(shí)現(xiàn)sharding-jdbc分庫分表的示例代碼
- SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫分表的實(shí)踐
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)分庫分表與讀寫分離的示例
- SpringBoot 2.0 整合sharding-jdbc中間件實(shí)現(xiàn)數(shù)據(jù)分庫分表
- SpringBoot整合sharding-jdbc?實(shí)現(xiàn)分庫分表操作的示例代碼
相關(guān)文章
使用arthas命令redefine實(shí)現(xiàn)Java熱更新(推薦)
今天分享一個(gè)非常重要的命令 redefine ,主要作用是加載外部的 .class 文件,用來替換 JVM 已經(jīng)加載的類,總結(jié)起來就是實(shí)現(xiàn)了 Java 的熱更新,感興趣的朋友跟隨小編一起看看吧2020-05-05Mybatis如何傳入多個(gè)參數(shù)的實(shí)現(xiàn)代碼
這篇文章主要介紹了Mybatis如何傳入多個(gè)參數(shù)的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Java中計(jì)算集合中元素的出現(xiàn)次數(shù)統(tǒng)計(jì)
本文主要介紹了Java中計(jì)算集合中元素的出現(xiàn)次數(shù)統(tǒng)計(jì),使用Collections類配合HashMap來統(tǒng)計(jì)和java lamb 計(jì)算這兩種方式,具有一定的參考價(jià)值,感興趣可以了解一下2024-02-02Java中數(shù)組array和列表list相互轉(zhuǎn)換
這篇文章主要介紹了Java中數(shù)組array和列表list相互轉(zhuǎn)換,在Java中,可以將數(shù)組(array)和列表(list)相互轉(zhuǎn)換,但需要注意一些細(xì)節(jié)和限制,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09Spring-boot oauth2使用RestTemplate進(jìn)行后臺自動(dòng)登錄的實(shí)現(xiàn)
這篇文章主要介紹了Spring-boot oauth2使用RestTemplate進(jìn)行后臺自動(dòng)登錄的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07