创建项目

一顿下一步,勾选web、lombok等插件

分表

导包

ShardingJdbc

官方最新稳定版4.1.1

<!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-spring-boot-starter -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>

Mysql

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>

Druid

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>

MyBatisPlus

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>

表结构

注意:之前我这表名叫table_0,结果一直报找不到表,后来发现,不能用关键字

CREATE TABLE `master_db`.`my_table_0` (
`id` BIGINT (20) NOT NULL,
`source` VARCHAR (20),
`remark` VARCHAR (100),
PRIMARY KEY (`id`)
); CREATE TABLE `master_db`.`my_table_1` (
`id` BIGINT (20) NOT NULL,
`source` VARCHAR (20),
`remark` VARCHAR (100),
PRIMARY KEY (`id`)
);

Yml

application-sharding_table.yml


server:
port: 80
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db #库名,只是名字
db: #数据源
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片规则
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志

至此配置完毕,运行效果见下方代码

分库

Yml

application-sharding_db.yml

spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db1,db2 #库名,只是名字
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db1.my_table
pub_table:
actualDataNodes: db2.pub_table
props:
sql:
show: true #输出日志

Java

Table0Controller.java中新增方法

    @GetMapping("saveByShardingDb")
public void saveByShardingDb(){
table0Service.save(new Table0(){{setSource("source");setRemark("remark");}});
pubTableService.save(new PubTable(){{setSource("source");setRemark("remark");}});
}

测试后可看到数据该去哪去哪了

分库分表

java代码都不改,只改数据库及yml

数据库

master_db、 slave_db1、 slave_db2

库中分别创建my_table_0、my_table_1,结构同 上

Yml

application-sharding_master_slave.yml

spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2 #库名,只是名字
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
#分库分表start
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db$->{0..2}.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
databaseStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: db$->{id % 3} #分片算法,分了三个库,所以要%3
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
#分库分表end
props:
sql:
show: true #输出日志

然后继续访问第一步的save&select方法就可看到效果了,配置文件中写的主从库没有实际意义,起错名字了,实际都会往里面写

读写分离

数据库

模拟主从,不做MySql真正的主从同步

上面做表分片时已经创建好了主库master_db 再创建两个库 slave_db1 slave_db2

三个库表结构一致

master_db表中无数据

slave_db1 表数据如下

​ "id" "source" "remark"

​ "1" "source1" "remark1"

slave_db2 表数据如下

​ "id" "source" "remark"

​ "1" "source2" "remark2"

Yml

application-master_slave.yml

spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: masterdb,slavedb1,slavedb2 #库名,只是名字
masterdb: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123 masterslave:
name: dbs
master-data-source-name: masterdb #主库
slave-data-source-names: slavedb1,slavedb2 #多个从库
load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机 ROUND_ROBIN 轮训
props:
sql:
show: true #输出日志

这时,访问上面搭好的项目,即可进行读写分离,代码见上方链接

其他

只请求主库

在请求上方添加如下代码即可

    //    HintManager hintManager = HintManager.getInstance();
// hintManager.setMasterRouteOnly();
@GetMapping("select")
public PageInfo select(int pageNum,int pageSize,Long id){
// HintManager hintManager = HintManager.getInstance();
// hintManager.setMasterRouteOnly();
PageHelper.startPage(pageNum,pageSize);
QueryWrapper<Table0> queryWrapper=new QueryWrapper();
if(!StringUtils.isEmpty(id)) {
queryWrapper.eq("id", id);
}
List<Table0> list = table0Service.list(queryWrapper);
PageInfo pageInfo = new PageInfo<>(list);
return pageInfo;
}

读写分离判断逻辑代码

大致的流程是shardingJdbc根据sql获得对应的sqlStatement,然后只有SelectStatement的才走从库

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.apache.shardingsphere.masterslave.route.engine.impl; import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.api.hint.HintManager;
import org.apache.shardingsphere.core.rule.MasterSlaveRule;
import org.apache.shardingsphere.sql.parser.sql.statement.SQLStatement;
import org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement; import java.util.ArrayList; /**
* Data source router for master-slave.
*/
@RequiredArgsConstructor
public final class MasterSlaveDataSourceRouter { private final MasterSlaveRule masterSlaveRule; /**
* Route.
*
* @param sqlStatement SQL statement
* @return data source name
*/
public String route(final SQLStatement sqlStatement) {
if (isMasterRoute(sqlStatement)) {
MasterVisitedManager.setMasterVisited();
return masterSlaveRule.getMasterDataSourceName();
}
return masterSlaveRule.getLoadBalanceAlgorithm().getDataSource(
masterSlaveRule.getName(), masterSlaveRule.getMasterDataSourceName(), new ArrayList<>(masterSlaveRule.getSlaveDataSourceNames()));
} private boolean isMasterRoute(final SQLStatement sqlStatement) {
return containsLockSegment(sqlStatement) || !(sqlStatement instanceof SelectStatement) || MasterVisitedManager.isMasterVisited() || HintManager.isMasterRouteOnly();
} private boolean containsLockSegment(final SQLStatement sqlStatement) {
return sqlStatement instanceof SelectStatement && ((SelecStatement) sqlStatement).getLock().isPresent();
}
}

一主多从+分表

上面实现了一主多从和表分片,现在把它整合到一起

java代码还是没改,主要改的还是Yml

Yml

application-sharding_db_table_oneMaster_slaves.yml

关键配置见 masterSlaveRule,分片配置未改

#一主多从+表分片
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2 #库名,只是名字
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
masterSlaveRule: # 这里配置这个规则的话,相当于是全局读写分离配置
name: ds_rw # 名称,合法的字符串即可,但如果涉及到在读写分离的基础上设置分库分表,则名称需要有意义才可以,另外,虽然目前没有强制要求,但主从库配置需要配置在实际关联的主从库上,如果配置的数据源之间主从是断开的状态,那么可能会发生写入的数据对于只读会话无法读取到的问题
# 如果一个会话发生了写入并且没有提交(显式打开事务),sharidng sphere在后续的路由中,select都会在主库执行,直到会话提交
masterDataSourceName: db0 # 主库的DataSource名称
slaveDataSourceNames: # 从库的DataSource列表,至少需要有一个
- db1
- db2
loadBalanceAlgorithmType: ROUND_ROBIN #从库负载均衡算法类型,可选值:ROUND_ROBIN,RANDOM。若loadBalanceAlgorithmClassName存在则忽略该配置,默认为ROUND_ROBIN
sharding: #指定表的分片规则
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db$->{0..2}.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
databaseStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: db$->{id % 3} #分片算法,分了三个库,所以要%3
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志

一主多从+分库分表

上面实现了一主多从和表分片,现在把它整合到一起

java代码还是没改,主要改的还是Yml

创建了两个主库两个从库master_db1、master_db2、slave_db1、slave_db2

下方配置为 master_db1slave_db1为主从关系、master_db2与slave_db2为主从关系

修改点有点多,查看标*****的位置

参考

Yml

application-sharding_db_table_masters_slaves.yml

#一主多从+表分片
spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2,db3 #库名,只是名字 ******************新增名称db3
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #主库1 ****************** 添加主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db3: #从库2 ******************添加从库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding:
master-slave-rules: # 新增配置 ******************
db0: # 此处名字一定要配置和下面 master-data-source-name 名字一致的
master-data-source-name: db0
slave-data-source-names: db2
db1: # 此处名字一定要配置和下面 master-data-source-name 名字一致的
master-data-source-name: db1
slave-data-source-names: db3
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db$->{0..1}.my_table_$->{0..1} #******************每组有一主一从,所以是0..1
databaseStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: db$->{(id / 10).toBigInteger() % 2} # *******不能再用id%2方式了,会导致数据分配不均,所以需要自定义方法
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志

公共表&数据脱敏

公共表

项目中会有很多字典表、配置表等等,此类表数据固定、量级不大,所以可以无需采用分库分表,每个库存一份;

当配置公共表后,每次对公共表进行操作,都会同步操作所有库中的公共表

数据库

分别在三个库中新增表pub_table

Java代码

生成pub_table相关的MybatisPlus代码

Yml

application-publicTable_encryptor.yml

spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db0,db1,db2 #库名,只是名字
db0: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db1?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
db2: #从库2
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/slave_db2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding:
default-data-source-name: db #如果有多个库,公共表只有一个库有,那么,就要指定有公共表的库,否则会报找不到表
default-database-strategy:
inline:
sharding-column: id
algorithm-expression: db$->{id % 3}
broadcast-tables: pub_table #公共表配置,可以多个
props:
sql:
show: true #输出日志

数据脱敏

参考

spring:
application:
name: shardingJdbcDemo
#shardingsphere相关配置
shardingsphere:
datasource:
names: db #库名,只是名字
db: #数据源
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/master_db?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
sharding: #指定表的分片规则
# 数据脱敏规则配置---start
encrypt-rule:
encryptors:
encryptor_MD5:
type: MD5
props:
md5.key.value: 123456
encryptor_aes:
# 加密、解密器的名字,内置的为MD5,aes.
# 可以自定义,实现
# org.apache.shardingsphere.encrypt.strategy.spi.Encryptor
# 或者
# org.apache.shardingsphere.encrypt.strategy.spi.QueryAssistedEncryptor
# 这两个接口即可
type: aes
props:
aes.key.value: 123456
tables:
# tables
my_table:
columns:
# 逻辑列,就是写SQL里面的列,因为实体类的名字和数据库的加密列一致,所以这里都是name
source:
# 原文列
# plainColumn: password
# 密文列,用来存储密文数据
cipherColumn: source
# 加密器名字
encryptor: encryptor_MD5
# password1:
# 原文列
# plainColumn: password1
# 密文列,用来存储密文数据
# cipherColumn: aes_password
# 加密器名字
# encryptor: encryptor_aes
# 数据脱敏规则配置---end
broadcast-tables: pub_table #公共表
tables: # 看到table "s" ,就知道可配置多个
my_table: # 指定表名,此名必须和model中 @TableName(value = "my_table") 一致
actualDataNodes: db.my_table_$->{0..1} #创建了两个表,下标0和1,所以此处配置你懂的
tableStrategy:
inline: # 指定表的分片策略
shardingColumn: id #参与分片运算的列名
algorithmExpression: my_table_$->{id % 2} #分片算法
keyGenerator: # 指定表的主键生成策略
type: SNOWFLAKE #SNOWFLAKE
column: id #指定主键
props:
sql:
show: true #输出日志
query.with.cipher.column: true #是否使用密文列查询

分布式事务

分库分表后,因为不是一个库了,所以一旦报错,数据无法回滚

Yml

使用上方 application-sharding_db_table_masters_slaves.yml

pom

        <!-- 使用 XA 事务时,需要引入此模块 -->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-transaction-spring-boot-starter</artifactId>
<version>3.1.0</version>
<type>pom</type>
</dependency>

Java

新增

package com.rollback.shardingjdbcdemo.demo.conf;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration
@EnableTransactionManagement
public class TransactionConfiguration { @Bean
public PlatformTransactionManager txManager(final DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
} @Bean
public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}

修改save方法

saveByTransaction

package com.rollback.shardingjdbcdemo.demo.sharding.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rollback.shardingjdbcdemo.demo.sharding.model.Table0;
import com.rollback.shardingjdbcdemo.demo.sharding.service.Table0Service;
import org.apache.shardingsphere.api.hint.HintManager;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.List;
import java.util.Random; /**
* <p>
* 前端控制器
* </p>
*
* @author koala
* @since 2021-05-31
*/
@RestController
@RequestMapping("/table0")
public class Table0Controller {
@Autowired
Table0Service table0Service; @GetMapping("save")
public void save(int tag){
table0Service.save(new Table0(){{setSource("source"+tag);setRemark("remark"+tag);}});
}
@Transactional
@ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE
@GetMapping("saveByTransaction")
public void saveByTransaction(int tag){
for (int i = 0; i < 10; i++) {
if(i==5){
List list=null;
list.add("error");
}
table0Service.save(new Table0(){{setSource("source"+tag);setRemark("remark"+tag);}});
}
} @GetMapping("select")
public PageInfo select(int pageNum,int pageSize,Long id){
// HintManager hintManager = HintManager.getInstance();
// hintManager.setMasterRouteOnly();
PageHelper.startPage(pageNum,pageSize);
QueryWrapper<Table0> queryWrapper=new QueryWrapper();
if(!StringUtils.isEmpty(id)) {
queryWrapper.eq("id", id);
}
queryWrapper.eq("source","source1");
List<Table0> list = table0Service.list(queryWrapper);
PageInfo pageInfo = new PageInfo<>(list);
return pageInfo;
} @GetMapping("select1")
public List<Table0> select1(int pageNum,int pageSize,Long id){
QueryWrapper<Table0> queryWrapper=new QueryWrapper();
if(!StringUtils.isEmpty(id)) {
queryWrapper.eq("id", id);
}
//queryWrapper.eq("source","source1");
List<Table0> list = table0Service.list(queryWrapper);
return list;
}
}

验证步骤:

  • 清空数据库

  • 执行saveByTransaction

  • 报错后观察数据库,一条都没有

  • 去掉

    ​ @Transactional

    ​ @ShardingTransactionType(TransactionType.XA) // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.BASE

    后,会出现保存部分数据的情况

参考官网

异常

如遇到 如下异常,只是一个健康检查的错误,可以通过添加 src/main/java/com/rollback/shardingjdbcdemo/demo/conf/DataSourceHealthConfig.java解决

ConnectionCallback; isValid; nested exception is java.sql.SQLFeatureNotSupportedException: isValid

代码下载

代码见sharding包下,请求入口见 Table0Controller

ShardingJdbc-分表;分库;分库分表;读写分离;一主多从+分表;一主多从+分库分表;公共表;数据脱敏;分布式事务的更多相关文章

  1. 分库分表(3) ---SpringBoot + ShardingSphere 实现读写分离

    分库分表(3)---ShardingSphere实现读写分离 有关ShardingSphere概念前面写了两篇博客: 1.分库分表(1) --- 理论 2. 分库分表(2) --- ShardingS ...

  2. 分库分表(7)--- SpringBoot+ShardingSphere实现分库分表 + 读写分离

    分库分表(7)--- ShardingSphere实现分库分表+读写分离 有关分库分表前面写了六篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理 ...

  3. sharing-jdbc实现读写分离及分库分表

    需求: 分库:按业务线business_id将不同业务线的订单存储在不同的数据库上: 分表:按user_id字段将不同用户的订单存储在不同的表上,为方便直接用非分片字段order_id查询,可使用基因 ...

  4. 分库分表(6)--- SpringBoot+ShardingSphere实现分表+ 读写分离

    分库分表(6)--- ShardingSphere实现分表+ 读写分离 有关分库分表前面写了五篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理论 ...

  5. 阿里P8架构师谈:数据库分库分表、读写分离的原理实现,使用场景

    本文转载自:阿里P8架构师谈:数据库分库分表.读写分离的原理实现,使用场景 为什么要分库分表和读写分离? 类似淘宝网这样的网站,海量数据的存储和访问成为了系统设计的瓶颈问题,日益增长的业务数据,无疑对 ...

  6. keeplived+mycat+mysql高可用读写分离水平分表(谁看谁都会)

    一:环境准备: 应用 主机 mysql-master 192.168.205.184 mysql-slave 192.168.205.185 mycat-01,keeplived,jdk 192.16 ...

  7. SpringBoot使用Sharding-JDBC读写分离

    本文介绍SpringBoot使用当当Sharding-JDBC进行读写分离. 1.有关Sharding-JDBC 本文还是基于当当网Sharding-Jdbc的依赖,与上一篇使用Sharding-Jd ...

  8. mycat读写分离

    版本:mycat1.0  只需要读写分离的功能,分库分表的都不需要. 涉及到的配置文件:  1.conf/server.xml  主要配置的是mycat的用户名和密码,mycat的用户名和密码和mys ...

  9. ProxySQL 配置详解及读写分离(+GTID)等功能说明 (完整篇)

    ProxySQL是灵活强大的MySQL代理层, 是一个能实实在在用在生产环境的MySQL中间件,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行 cache,支持动态加载配 ...

随机推荐

  1. 【Python爬虫】爬虫利器 requests 库小结

    requests库 Requests 是一个 Python 的 HTTP 客户端库. 支持许多 HTTP 特性,可以非常方便地进行网页请求.网页分析和处理网页资源,拥有许多强大的功能. 本文主要介绍 ...

  2. Java8之Stream常用操作方式

    哈喽!大家好,我是[学无止境小奇],一位热爱分享各种技术的博主! [学无止境小奇]的创作宗旨:每一条命令都亲自执行过,每一行代码都实际运行过,每一种方法都真实实践过,每一篇文章都良心制作过. [学无止 ...

  3. Linux 查看运行中进程的 umask

    线上某台虚机因为故障重装了系统(基线 CentOS 6.9 内核 2.6.x),重新部署了应用.这个应用会生成一个文件,到NFS挂载目录. 而这个 NFS 挂载目录是一个 FTP 服务器的目录.另一台 ...

  4. Plist存储

  5. NSString为何要用copy修饰,而不是strong?

    NSString本身是无所谓的,但是如果一个 NSString 指针指向了一个 NSMutableString的内存空间的话,如果使用 strong 修饰的话,如果你在别处修改这个值的话,那么原来的值 ...

  6. NSString基本概念

    1.NSString基本概念 什么是NSString? 一个NSString对象就代表一个字符串(文字内容) 一般称NSString为字符串类 2.NSString创建方式 最直接的方式(常量字符串) ...

  7. zeppelin安装及配置

    1.下载安装包,zepplin下载地址:http://zeppelin.apache.org/download.html #创建解压目录 mkdir -p /opt/software #解压 tar ...

  8. 暑假撸系统6- Thymeleaf ajax交互!

    本来用Thymeleaf也没想着深度使用ajax,就是用也是非常传统的ajax方式提交然后js控制修改下变量.闲来无事的时候看Thymeleaf的教程发现一哥们的实现方式,以及实现思路,堪称惊奇,先说 ...

  9. zabbix主动上报mysql数据库内容

    zabbix_sender命令支持主动上报数据,web服务端添加对应机器和采集器即可. 2015年刚接触zabbix时候,用的上报sqlserver脚本是select数据后插入到临时表,bcp下载到本 ...

  10. Java高性能本地缓存框架Caffeine

    一.序言 Caffeine是一个进程内部缓存框架,使用了Java 8最新的[StampedLock]乐观锁技术,极大提高缓存并发吞吐量,一个高性能的 Java 缓存库,被称为最快缓存. 二.缓存简介 ...