数据库相关知识脉络图
目录
ShardingSphere简介
ShardingSphere是一套开源的分布式数据库解决方案组成的生态圈,包含:
- ShardingSphere JDBC
- 核心功能:分库分表 & 读写分离
- 引入进我们程序中,提供api去操作分库分表的jar包。
- 任意jdbc型数据库都可以使用。
- 侵入性强,也灵活。
- ShardingSphere Proxy
- 隔离在我们程序之外的应用,提供操作分库分表功能。
- 仅供MySQL,PostgreSQL使用。
- 独立部署,需提前定义好与数据库交互的逻辑。
- Sidecar(规划中)
什么情况下考虑分库分表呢?
- 单表数据未来三年超过500万数据
- 单表数据大小未来三年超过2G
- 根据实际业务
ShardingSphere JDBC基本概念解释
序号 | 名词 | 解释 |
---|---|---|
1 | 逻辑表 | 把一类相同的表、相同增删改查逻辑的表,抽象成一个“逻辑表”,不真实存在。 |
2 | 真实表 | 真实存在的表 |
3 | 广播表 | 所有库里这个表的逻辑字段使用逻辑都相同的表,例如数据字典表要统一。 |
4 | 绑定表 | 像是主表和子表的关系,不可分割,尽量保持一致的表。 |
5 | 分片键 | 例如插入数据时候,根据哪个字段来路由数据进入到各个库表?那个字段就是分片键 |
6 | 分片算法 | 根据什么算法去路由?取摩运算?直接指定库名? |
7 | 分片策略 | = 分片键 + 分片算法 |
ShardingSphere JDBC使用
demo地址github
https://github.com/lxnxxwl/shardingspheredemo.git
经典三步:
1、 建表:例如mall_order_1 \ mall_order_2..这样尾数有关联易表达的。
2、 引入sharding sphere jdbc的依赖
3、 编写配置文件
demo介绍:
- maven聚合项目:common包中实体类,其他包为不同配置的分库分表demo依赖common。
- 使用mybatis plus 进行操作数据库(测试用例简单)。mapper在各个demo包中。
- 测试例子在各个demo的test包中。
- 配置文件采用.properties文件配置。
单库分表
- 首先要自己建表(真实表):
- 这里就是在一个数据库里建两张相同的表mall_order_1 \ mall_order_2。
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for mall_order_1
-- ----------------------------
DROP TABLE IF EXISTS `mall_order_1`;
CREATE TABLE `mall_order_1` (
`id` bigint NOT NULL,
`order_name` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
- 引入pom依赖。
- springboot为例
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
- 编写配置文件【单库分表】
#sharding jdbc 数据库 起名 m1
spring.shardingsphere.datasource.names=m1
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=root
# 1.哪些节点?==哪几张表
spring.shardingsphere.sharding.tables.mall_order.actual-data-nodes=m1.mall_order_$->{1..2}
# 2.主键是哪一列?
spring.shardingsphere.sharding.tables.mall_order.key-generator.column=cid
# 3.主键生成策略是什么? 可自定义,此处采用已集成的雪花算法
spring.shardingsphere.sharding.tables.mall_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.mall_order.key-generator.props.worker.id=1
# 4.分片键:inline模式下按id分表
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.sharding-column=cid
# 5.分片算法:ID取摩
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.algorithm-expression=mall_order_$->{cid%2+1}
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true
- mapper:
public interface MallOrderMapper extends BaseMapper<MallOrder> {
}
- 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class OnedbApplicationTests {
@Resource
private MallOrderMapper orderMapper;
@Test
public void addOrder(){
for(int i = 0 ; i < 10 ; i ++){
MallOrder order = new MallOrder();
order.setOrderName("第"+i+"个订单");
orderMapper.insert(order);
}
}
}
分库分表-inline模式-普通不支持范围查询
- 首先要自己建表(真实表):
- 这里就是在test数据库里建两张相同的表mall_order_1 \ mall_order_2。在test2中建两张相同的表mall_order_1 \ mall_order_2 。建表语句同上。
- 依赖同上:放在父工程pom里即可
- 配置文件:
# 应用名称
spring.application.name=twodb
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.mall_order.actual-data-nodes=db$->{1..2}.mall_order_$->{1..2}
#使用雪花算法自动生成id/主键生成策略
spring.shardingsphere.sharding.tables.mall_order.key-generator.column=id
spring.shardingsphere.sharding.tables.mall_order.key-generator.type=SNOWFLAKE
#spring.shardingsphere.sharding.tables.mall_order.key-generator.props.worker.id=1
#分片(分表:table-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.sharding-column=id
#分片算法:根据ID是奇数->mall_order_1;是偶数->mall_order_2
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.algorithm-expression=mall_order_$->{id%2+1}
#分片(分库:database-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.database-strategy.inline.sharding-column=id
#分片算法:根据ID是奇数->db1 = test;是偶数->db2 = test2
spring.shardingsphere.sharding.tables.mall_order.database-strategy.inline.algorithm-expression=db$->{id%2+1}
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true
- mapper同上
- 测试用例
@SpringBootTest
@RunWith(SpringRunner.class)
public class TwodbApplicationTests {
@Resource
private MallOrderMapper orderMapper;
/**
* 向两个数据库四张表插入数据
*/
@Test
public void addOrderToDB() {
for(int i = 0 ; i < 10 ; i ++){
MallOrder order = new MallOrder();
order.setOrderName("分库后的第"+i+"个订单");
orderMapper.insert(order);
}
}
/**
* 按id查找某条数据
* Logic SQL: SELECT id,order_name FROM mall_order WHERE (id = ?)
* Actual SQL: db2 ::: SELECT id,order_name FROM mall_order_2
* shardingsphere已经按策略优化查询sql,仅在id可能存在的test2库的mall_order_2这张表中进行一次查询
*/
@Test
public void queryDataById(){
QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
wrapper.eq("id",1415550634731560961L);
MallOrder mallOrder = orderMapper.selectOne(wrapper);
System.out.println(mallOrder);
}
/**
* 范围查询:ID在xxx~zzz之间的所有数据查询
* Inline strategy cannot support this type sharding:RangeRouteValue
* 使用inline模式是不支持范围查询的
*/
@Test
public void queryDataByRang(){
QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
wrapper.between("id",1415550634731560961L,1415550634748338178L);
List<MallOrder> mallOrders = orderMapper.selectList(wrapper);
mallOrders.forEach(mallOrder -> System.out.println(mallOrder));
}
/**
* 按id排序查询出所有数据
* Logic SQL: SELECT id,order_name FROM mall_order
* Actual SQL: db1 ::: SELECT id,order_name FROM mall_order_1
* Actual SQL: db1 ::: SELECT id,order_name FROM mall_order_2
* Actual SQL: db2 ::: SELECT id,order_name FROM mall_order_1
* Actual SQL: db2 ::: SELECT id,order_name FROM mall_order_2
* 两个库的四张表全部查询一遍(有待优化)
*/
@Test
public void queryDataBySort(){
QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");
List<MallOrder> mallOrders = orderMapper.selectList(wrapper);
mallOrders.forEach(mallOrder -> System.out.println(mallOrder));
}
}
注:inline模式不支持范围查询,使用standard自定义规则后实现范围查询
分库分表-standard模式-范围查询
- 相同的sql和依赖和mapper省略
- 配置文件
# 应用名称
spring.application.name=twodb-standard
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.mall_order.actual-data-nodes=db$->{1..2}.mall_order_$->{1..2}
#使用雪花算法自动生成id/主键生成策略
spring.shardingsphere.sharding.tables.mall_order.key-generator.column=id
spring.shardingsphere.sharding.tables.mall_order.key-generator.type=SNOWFLAKE
#spring.shardingsphere.sharding.tables.mall_order.key-generator.props.worker.id=1
#分片(分表:table-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.table-strategy.standard.sharding-column=id
#分表算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.table-strategy.standard.precise-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyTablePreciseAlgorithm
#表范围查询算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.table-strategy.standard.range-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyTableRangeAlgorithm
#分片(分库:database-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.database-strategy.standard.sharding-column=id
#分库算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.database-strategy.standard.precise-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyDBPreciseAlgorithm
#库范围查找算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.database-strategy.standard.range-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyDBRangeAlgorithm
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true
- 自己写实现类:自己实现分库分表的规则,自己实现范围查询的方法等等
- 自己实现分库策略
/**
* @Description : TODO 自己实现分库策略
* @Author : lixiunan
* @Date : 2021/7/15
**/
public class MyDBPreciseAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
//把雪花算法生成的id取出
Long id = shardingValue.getValue();
//对id取摩得到的数字
BigInteger key =
BigInteger.valueOf(id).mod(new BigInteger("2")).add(new BigInteger("1"));
//生成真实表的表名
String dbName = "db" + key;
if(availableTargetNames.contains(dbName)){
return dbName;
}
throw new UnsupportedOperationException("找不到数据库");
}
}
- 自己实现分表策略
/**
* @Description :
* TODO 自己定制insert时按照什么算法去分发到不同表中:分片键的类型Lone传入泛型,确保此算法在范围查找时使用是有效的
* @Author : lixiunan
* @Date : 2021/7/15
**/
public class MyTablePreciseAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
//把雪花算法生成的id取出
Long id = shardingValue.getValue();
//对id取摩得到表名的数字
BigInteger key =
BigInteger.valueOf(id).mod(new BigInteger("2")).add(new BigInteger("1"));
//生成真实表的表名
String tableName = shardingValue.getLogicTableName() + "_" + key;
if(availableTargetNames.contains(tableName)){
return tableName;
}else {
throw new UnsupportedOperationException("找不到表名");
}
}
}
- 自己实现范围查找(库 + 表)
/**
* @Description : TODO 分为查找时分库策略定制
* @Author : lixiunan
* @Date : 2021/7/15
**/
public class MyDBRangeAlgorithm implements RangeShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(
Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
//范围查询库
return Arrays.asList("db1","db2");
}
}
/**
* @Description : TODO 定制范围查找时分表查找策略
* @Author : lixiunan
* @Date : 2021/7/15
**/
public class MyTableRangeAlgorithm implements RangeShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(
Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
String logicTableName = shardingValue.getLogicTableName();
//范围查询表
return Arrays.asList(logicTableName+"_1",logicTableName+"_2");
}
}
- 测试用例
@SpringBootTest
@RunWith(SpringRunner.class)
public class TwodbStandardApplicationTests {
@Resource
private MallOrderMapper orderMapper;
/**
* 向两个数据库四张表插入数据
*/
@Test
public void addOrderToDB() {
for(int i = 0 ; i < 10 ; i ++){
MallOrder order = new MallOrder();
order.setOrderName("standard中第"+i+"个订单");
orderMapper.insert(order);
}
}
/**
* 范围查询:
* Logic SQL: SELECT id,order_name FROM mall_order WHERE (id BETWEEN ? AND ?)
* Actual SQL: db1 ::: SELECT id,order_name FROM mall_order_1 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
* Actual SQL: db1 ::: SELECT id,order_name FROM mall_order_2 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
* Actual SQL: db2 ::: SELECT id,order_name FROM mall_order_1 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
* Actual SQL: db2 ::: SELECT id,order_name FROM mall_order_2 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
*
*
* 使用inline模式是不支持范围查询的,standard可以按照算法提供的方法或表名库名进行范围查找
*/
@Test
public void queryDataByRang(){
QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
wrapper.between("id",1415550634731560961L,1415550634748338178L);
List<MallOrder> mallOrders = orderMapper.selectList(wrapper);
mallOrders.forEach(mallOrder -> System.out.println(mallOrder));
}
}
分库分表-complex模式-混合字段范围查询
- 相同的sql和依赖和mapper省略
- 配置文件
# 应用名称
spring.application.name=twodb-complex
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.product.actual-data-nodes=db$->{1..2}.product_$->{1..2}
#分片(分表:table-strategy)策略
#分片键ID:可以多个ID联合
spring.shardingsphere.sharding.tables.product.table-strategy.complex.sharding-columns=id,store_id
#分表算法(需自己实现):
spring.shardingsphere.sharding.tables.product.table-strategy.complex.algorithm-class-name=com.lixiunan.twodbcomplex.algorithm.MyComplexTableAlgorithm
#分片(分库:database-strategy)策略
#分片键ID:#分片键ID:
spring.shardingsphere.sharding.tables.product.database-strategy.complex.sharding-columns=id,store_id
#分库算法(需自己实现):
spring.shardingsphere.sharding.tables.product.database-strategy.complex.algorithm-class-name=com.lixiunan.twodbcomplex.algorithm.MyComplexDBAlgorithm
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true
自己实现存储&范围查找(库 + 表) 的策略
public class MyComplexDBAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
//获取店铺ID集合
Collection<Long> storeIdCollection =
shardingValue.getColumnNameAndShardingValuesMap().get("store_id");
//创建新集合
ArrayList<String> result = new ArrayList<String>();
//策略为取摩尔
for (Long storeId : storeIdCollection){
BigInteger storeIdInteger = BigInteger.valueOf(storeId);
BigInteger key =
(storeIdInteger.mod(new BigInteger("2"))).add(new BigInteger("1"));
result.add("db"+key);
}
return result;
}
}
public class MyComplexTableAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
//获取店铺ID集合
Collection<Long> storeIdCollection =
shardingValue.getColumnNameAndShardingValuesMap().get("store_id");
//获取真实表前缀名称
String logicTableName = shardingValue.getLogicTableName();
//创建新集合
ArrayList<String> result = new ArrayList<String>();
//策略为取摩尔
for (Long storeId : storeIdCollection){
BigInteger storeIdInteger = BigInteger.valueOf(storeId);
BigInteger key =
(storeIdInteger.mod(new BigInteger("2"))).add(new BigInteger("1"));
result.add(logicTableName+"_"+key);
}
return result;
}
}
测试类——支持混合id范围条件查询
@RunWith(SpringRunner.class)
@SpringBootTest
public class TwodbComplexApplicationTests {
@Resource
private ProductMapper productMapper;
@Resource
private StoreMapper storeMapper;
/**
*添加数据
*/
@Test
public void add() {
for(int i = 0 ; i < 10 ; i ++){
Product product = new Product();
Long idLong = Long.valueOf(202110L + i);
product.setId(idLong);
Long storeIdLong = Long.valueOf(676 + i);
product.setStoreId(storeIdLong);
product.setProductName("complex第"+i+"个商品");
product.setProductStatus(((i % 2)+1)+"");
productMapper.insert(product);
}
}
/**
* 缺少参数不能查询
*/
@Test
public void queryRange(){
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.between("store_id",670L,680L);
List<Product> products = productMapper.selectList(wrapper);
products.forEach(product -> System.out.println(product));
}
/**
* 支持(必须)混合ID复杂查询,如配置中的
*/
@Test
public void queryCourseComplex(){
QueryWrapper<Product> wrapper = new QueryWrapper<>();
wrapper.between("id",202100L,202114L);
wrapper.eq("store_id",677L);
List<Product> products = productMapper.selectList(wrapper);
products.forEach(product -> System.out.println(product));
}
}
分库分表-hint模式-指定数据库/表
- 相同的sql和依赖和mapper省略
- 配置文件
# 应用名称
spring.application.name=twodb-hint
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.product.actual-data-nodes=db$->{1..2}.product_$->{1..2}
#使用雪花算法自动生成id/主键生成策略
spring.shardingsphere.sharding.tables.product.key-generator.column=id
spring.shardingsphere.sharding.tables.product.key-generator.type=SNOWFLAKE
#分片(分表:table-strategy)策略
#分片键ID:可以多个ID联合
#分表算法(需自己实现hint模式):
spring.shardingsphere.sharding.tables.product.table-strategy.hint.algorithm-class-name=com.lixiunan.twodbhint.algorithm.MyHintTableAlgorithm
#分片(分库:database-strategy)策略
#分片键ID:#分片键ID:
#分库算法:不指定
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true
自己实现如何制定表/库
/**
* @Description : TODO hint可向指定表/库中添加/获取数据
* @Author : lixiunan
* @Date : 2021/7/19
**/
public class MyHintTableAlgorithm implements HintShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Long> shardingValue) {
String key =
shardingValue.getLogicTableName() + "_" + shardingValue.getValues().toArray()[0];
if(availableTargetNames.contains(key)){
return Arrays.asList(key);
}
throw new UnsupportedOperationException("找不到表");
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class TwodbHintApplicationTests {
@Resource
private ProductMapper productMapper;
/**
* 指定查询的表
* SELECT id,store_id,product_name,product_status FROM product
* Actual SQL: db1 ::: SELECT id,store_id,product_name,product_status FROM product_1
* Actual SQL: db2 ::: SELECT id,store_id,product_name,product_status FROM product_1
*/
@Test
public void queryByHint1(){
HintManager hintManager = HintManager.getInstance();
hintManager.addTableShardingValue("product",1);
List<Product> products = productMapper.selectList(null);
products.forEach(product -> System.out.println(product));
hintManager.close();
}
/**
* Logic SQL: SELECT id,store_id,product_name,product_status FROM product
* Actual SQL: db1 ::: SELECT id,store_id,product_name,product_status FROM product_2
* Actual SQL: db2 ::: SELECT id,store_id,product_name,product_status FROM product_2
*/
@Test
public void queryByHint2(){
HintManager hintManager = HintManager.getInstance();
hintManager.addTableShardingValue("product",2);
List<Product> products = productMapper.selectList(null);
products.forEach(product -> System.out.println(product));
hintManager.close();
}
}