sharding-jdbc5.0.0實(shí)現(xiàn)分表實(shí)踐
本文基于shardingsphere-jdbc-core-spring-boot-starter 5.0.0,請(qǐng)注意不同版本的sharding-jdbc配置可能有不一樣的地方,本文不一定適用于其它版本
相關(guān)的maven配置如下:
? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.springframework.boot</groupId> ? ? ? ? ? ? <artifactId>spring-boot-starter-data-jpa</artifactId> ? ? ? ? </dependency> ? ? ? ?<dependency> ? ? ? ? ? ? <groupId>org.apache.shardingsphere</groupId> ? ? ? ? ? ? <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> ? ? ? ? ? ? <version>5.0.0</version> ? ? ? ? </dependency> ? ? ? <dependency> ? ? ? ? ? ? <groupId>mysql</groupId> ? ? ? ? ? ? <artifactId>mysql-connector-java</artifactId> ? ? ? ? </dependency>
以下為單庫分表的配置,根據(jù)對(duì)象的trade_no字段hash后mod進(jìn)行分片,把數(shù)據(jù)分散到12個(gè)表中
spring: ? shardingsphere: ? ? datasource: ?##數(shù)據(jù)源配置 ? ? ? ds0: ? ? ? ? driver-class-name: com.mysql.jc.jdbc.Driver ? ? ? ? jdbc-url: jdbc:mysql://... ? ? ? ? password: ... ? ? ? ? type: com.zaxxer.hikari.HikariDataSource ? ? ? ? username: root ? ? ? names: ds0 ? ? mode: ? ? ? type: Memory ? ? props: ? ? ? sql-show: false ##為true時(shí)會(huì)打印sharding-jdbc生成的邏輯sql跟實(shí)際執(zhí)行語句 ? ? rules: ##分片規(guī)則配置 ? ? ? sharding: ? ? ? ? binding-tables: ? ? ? ? - trade_info ? ? ? ? sharding-algorithms: ? ? ? ? ? trade-info-inline: ?#分片算法配置 ? ? ? ? ? ? props: ? ? ? ? ? ? ? sharding-count: '12' ? ? ? ? ? ? type: HASH_MOD ? ? ? ? tables: ? ? ? ? ? trade_info: ? ? ? ? ? ? actual-data-nodes: ds0.trade_info_$->{0..11} ? ? ? ? ? ? table-strategy: ? ? ? ? ? ? ? standard: ? ? ? ? ? ? ? ? sharding-algorithm-name: trade-info-inline ?##使用的分片算法名 ? ? ? ? ? ? ? ? sharding-column: trade_no ?##分片鍵
jpa提供了TABLE(使用一個(gè)特定的數(shù)據(jù)庫表格來保存主鍵,在使用時(shí)從該表取數(shù)據(jù)做為主鍵)、SEQUENCE(由底層數(shù)據(jù)庫的序列來生成主鍵,需要數(shù)據(jù)庫支持序列)、IDENTITY(由數(shù)據(jù)庫自動(dòng)生成主鍵,主要在自增ID列使用 )三種生成主鍵值的策略。但對(duì)于分庫分表來講都不太適用,所以自定義了一個(gè)使用雪花算法來生成主鍵值
public class SnowFlakeIdGenerator implements IdentifierGenerator { ? ? @Override ? ? public Serializable generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException { ? ? ? ? return SnowFlakeUtil.nextId(); ? ? } ? ? @Override ? ? public boolean supportsJdbcBatchInserts() { ? ? ? ? return true; ? ? } }
實(shí)體類id的配置
? ? @Id ? ? @GenericGenerator(name = "snowflake",strategy = "com.****.****.****.SnowFlakeIdGenerator") ? ? @GeneratedValue(generator = "snowflake") ? ? private Long id;
配置完后,試了下新增、刪除、查詢都沒有問題,但更新記錄的時(shí)候出錯(cuò)了,報(bào)錯(cuò)信息為ShardingSphereException: Can not update sharding key, logic table: [**], column: [**]。從報(bào)錯(cuò)信息看來是因?yàn)槲腋铝嗽杏涗浀姆制I,奇怪的
? ? public void preValidate(ShardingRule shardingRule, SQLStatementContext<UpdateStatement> sqlStatementContext, List<Object> parameters, ShardingSphereSchema schema) { ? ? ? ? this.validateMultipleTable(shardingRule, sqlStatementContext); ? ? ? ? UpdateStatement sqlStatement = (UpdateStatement)sqlStatementContext.getSqlStatement(); ? ? ? ? String tableName = (String)sqlStatementContext.getTablesContext().getTableNames().iterator().next(); ? ? ? ? Iterator var7 = sqlStatement.getSetAssignment().getAssignments().iterator(); ? ? ? ? String shardingColumn; ? ? ? ? Optional shardingColumnSetAssignmentValue; ? ? ? ? Optional shardingValue; ? ? ? ? do { ? ? ? ? ? ? AssignmentSegment each; ? ? ? ? ? ? do { ? ? ? ? ? ? ? ? if (!var7.hasNext()) { ? ? ? ? ? ? ? ? ? ? return; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? each = (AssignmentSegment)var7.next(); ? ? ? ? ? ? ? ? shardingColumn = ((ColumnSegment)each.getColumns().get(0)).getIdentifier().getValue(); ? ? ? ? ? ? } while(!shardingRule.isShardingColumn(shardingColumn, tableName)); ? ? ? ? ? ? shardingColumnSetAssignmentValue = this.getShardingColumnSetAssignmentValue(each, parameters); ? ? ? ? ? ? shardingValue = Optional.empty(); ? ? ? ? ? ? Optional<WhereSegment> whereSegmentOptional = sqlStatement.getWhere(); ? ? ? ? ? ? if (whereSegmentOptional.isPresent()) { ? ? ? ? ? ? ? ? shardingValue = this.getShardingValue((WhereSegment)whereSegmentOptional.get(), parameters, shardingColumn); ? ? ? ? ? ? } ? ? ? ? } while(shardingColumnSetAssignmentValue.isPresent() && shardingValue.isPresent() && shardingColumnSetAssignmentValue.get().equals(shardingValue.get())); ? ? ? ? throw new ShardingSphereException("Can not update sharding key, logic table: [%s], column: [%s].", new Object[]{tableName, shardingColumn}); ? ? }
是我并沒有更新分片鍵,調(diào)用棧中最開始出錯(cuò)的代碼如下:
這方法在做的事情就是,如果update語句的set里面存在分片鍵,將會(huì)從where中獲取的分片鍵的值,然后將where語句中獲取到分片鍵值跟set語句中的分片鍵值比較是否發(fā)生改變,發(fā)生改變就會(huì)拋出ShardingSphereException。比如我的trade_info表分片鍵為trade_no,執(zhí)行的更新語句為update trade_info t set t.trade_no = 123,t.a = 1 where t.trade_no = 123,這段代碼就會(huì)去比較set中trade_no與where中trade_no的值是否一樣,不一樣或者where中沒有分片鍵而set中包含分片鍵就會(huì)拋異常。
打印了一下執(zhí)行的update語句,我提交的更新語句為update t set t.b = ? where t.a = ?,被sharding-jdbc攔下來檢查時(shí)語句變成了update t set t.a = ? ,t.b = ?,t.c = ? where t.id = ? ,語句發(fā)生了兩個(gè)變化:我原本語句只是更新了對(duì)象的部分屬性,執(zhí)行語句變成了全量更新;where子句被改變了,原本更新的條件是t.a=?,提交執(zhí)行時(shí)變成了t.id=?。原因是JPA對(duì)語句做了優(yōu)化,修改了我寫的語句,實(shí)體類中加上注解@DynamicUpdate,更新時(shí)只更新發(fā)生改變的字段,解決了問題。
更多的功能配置可以參考官方文檔:https://shardingsphere.apache.org/document/5.0.0/cn/user-manual/shardingsphere-jdbc/
到此這篇關(guān)于sharding-jdbc5.0.0實(shí)現(xiàn)分表實(shí)踐的文章就介紹到這了,更多相關(guān)sharding-jdbc5.0.0分表 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 利用Sharding-Jdbc進(jìn)行分庫分表的操作代碼
- 使用sharding-jdbc實(shí)現(xiàn)水平分庫+水平分表的示例代碼
- springboot實(shí)現(xiàn)以代碼的方式配置sharding-jdbc水平分表
- 使用sharding-jdbc實(shí)現(xiàn)水平分表的示例代碼
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫分表的實(shí)踐
- SpringBoot整合sharding-jdbc實(shí)現(xiàn)分庫分表與讀寫分離的示例
- Java使用Sharding-JDBC分庫分表進(jìn)行操作
- Sharding-Jdbc 自定義復(fù)合分片的實(shí)現(xiàn)(分庫分表)
- 利用Sharding-Jdbc組件實(shí)現(xiàn)分表
相關(guān)文章
Java中synchronized關(guān)鍵字的使用和原理詳解
這篇文章主要介紹了Java中synchronized關(guān)鍵字的使用和原理詳解,JVM 是通過進(jìn)入、退出 對(duì)象監(jiān)視器(Monitor)來實(shí)現(xiàn)對(duì)方法、同步塊的同步的,而對(duì)象監(jiān)視器的本質(zhì)依賴于底層操作系統(tǒng)的互斥鎖實(shí)現(xiàn),需要的朋友可以參考下2023-09-09intellij idea快速查看當(dāng)前類中的所有方法(推薦)
這篇文章主要介紹了intellij idea快速查看當(dāng)前類中的所有方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09java關(guān)鍵字static學(xué)習(xí)心得
本篇文章給大家分享一篇關(guān)于java關(guān)鍵字static的學(xué)習(xí)心得,有這方面需要的朋友學(xué)習(xí)下吧。2018-01-01RocketMQ之NameServer架構(gòu)設(shè)計(jì)及啟動(dòng)關(guān)閉流程源碼分析
這篇文章主要為大家介紹了RocketMQ之NameServer架構(gòu)設(shè)計(jì)及啟動(dòng)關(guān)閉流程源碼分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11openEuler?搭建java開發(fā)環(huán)境的詳細(xì)過程
這篇文章主要介紹了openEuler?搭建java開發(fā)環(huán)境,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06手寫簡(jiǎn)版kedis分布式key及value服務(wù)的實(shí)現(xiàn)及配置
這篇文章主要為大家介紹了手寫簡(jiǎn)版的kedis分布式key及value服務(wù)的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02