分表操作是水平分的。比如一个表记录超过100000,那么1-100000在第一个表,100000以上在另一个表。(而且这两个表的字段是一样的
先根据company_id奇偶进行分库、再根据id的奇偶进行分表(比如奇数在0表,偶数就在1表)

1、在数据库创建真实表

在两个库中都创建表(b_order0、b_order1)

  1. CREATE TABLE `b_order`(
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3. `is_del` bit(1) NOT NULL DEFAULT 0 COMMENT '是否被删除',
  4. `company_id` int(11) NOT NULL COMMENT '公司ID',
  5. `position_id` bigint(11) NOT NULL COMMENT '职位ID',
  6. `user_id` int(11) NOT NULL COMMENT '用户id',
  7. `publish_user_id` int(11) NOT NULL COMMENT '职位发布者id',
  8. `resume_type` int(2) NOT NULL DEFAULT 0 COMMENT '简历类型:0 附件 1 在线',
  9. `status` varchar(256) NOT NULL COMMENT '投递状态 投递状态 WAIT-待处理 AUTO_FILTER-自动过滤 PREPARE_CONTACT-待沟通 REFUSE-拒绝 ARRANGE_INTERVIEW-通知面试',
  10. `create_time` datetime NOT NULL COMMENT '创建时间',
  11. `operate_time` datetime NOT NULL COMMENT '操作时间',
  12. `work_year` varchar(100) DEFAULT NULL COMMENT '工作年限',
  13. `name` varchar(256) DEFAULT NULL COMMENT '投递简历人名字',
  14. `position_name` varchar(256) DEFAULT NULL COMMENT '职位名称',
  15. `resume_id` int(10) DEFAULT NULL COMMENT '投递的简历id(在线和附件都记录,通过resumeType进行区别在线还是附件)',
  16. PRIMARY KEY (`id`),
  17. KEY `index_createTime` (`create_time`),
  18. KEY `index_companyId_status` (`company_id`, `status`(255), `is_del`),
  19. KEY `i_comId_pub_ctime` (`company_id`, `publish_user_id`, `create_time`),
  20. KEY `index_companyId_positionId` (`company_id`, `position_id`) USING BTREE
  21. ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

image.png image.png

2、创建实体类

  1. package com.slin.entity;
  2. import javax.persistence.*;
  3. import java.io.Serializable;
  4. import java.util.Date;
  5. @Entity
  6. @Table(name = "b_order") // 用的是逻辑表名(真实表是b_order0、b_order1)
  7. public class BOrder implements Serializable {
  8. @Id
  9. @Column(name = "id")
  10. @GeneratedValue(strategy = GenerationType.IDENTITY)
  11. private long id;
  12. @Column(name = "is_del")
  13. private Boolean isDel;
  14. @Column(name = "company_id")
  15. private Integer companyId;
  16. @Column(name = "position_id")
  17. private long positionId;
  18. @Column(name = "user_id")
  19. private Integer userId;
  20. @Column(name = "publish_user_id")
  21. private Integer publishUserId;
  22. @Column(name = "resume_type")
  23. private Integer resumeType;
  24. @Column(name = "status")
  25. private String status;
  26. @Column(name = "create_time")
  27. private Date createTime;
  28. @Column(name = "operate_time")
  29. private Date operateTime;
  30. @Column(name = "work_year")
  31. private String workYear;
  32. @Column(name = "name")
  33. private String name;
  34. @Column(name = "position_name")
  35. private String positionName;
  36. @Column(name = "resume_id")
  37. private Integer resumeId;
  38. // get/set的方法
  39. }

3、创建repository

  1. package com.slin.repository;
  2. import com.slin.entity.BOrder;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. public interface BOrderRepository extends JpaRepository<BOrder,Long> {
  5. }

4、添加配置信息

image.png

######datasource(数据源,有两个库)#######
spring.shardingsphere.datasource.names=ds0,ds1

######配置第一个库#######
#使用连接池
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
#使用驱动
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
#数据库连接(如果是服务器的就只需要把localhost改为服务器的ip即可)
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/lagou1
#数据库用户和密码
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=root

######配置第二个库#######
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/lagou2
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root


###########sharding-database-strategy实现分库规则#####
#对b_order实现分库的操作(根据企业id进行分的)----是实体类中的逻辑表名b_order
spring.shardingsphere.sharding.tables.b_order.database-strategy.inline.sharding-column=company_id
#如何定位呢,是根据ds$->{company_id % 2}来定位
spring.shardingsphere.sharding.tables.b_order.database-strategy.inline.algorithm-expression=ds$->{company_id % 2}

###########sharding-database-strategy实现分表规则#####
#对Border实现分表的操作(根据id进行分)
spring.shardingsphere.sharding.tables.b_order.table-strategy.inline.sharding-column=id
#如何定位呢,是根据ds$->{id % 2}来定位
spring.shardingsphere.sharding.tables.b_order.table-strategy.inline.algorithm-expression=b_order$->{id % 2}

#####目前配置的是逻辑表,那么要分配到那个库那个真实表上呢,这个就涉及到数据节点的问题
spring.shardingsphere.sharding.tables.b_order.actual-data-nodes=ds${0..1}.b_order${0..1}
#id的主键生成器(配置之后就会采用系统内置的雪花算法)
spring.shardingsphere.sharding.tables.b_order.key-generator.column=id
spring.shardingsphere.sharding.tables.b_order.key-generator.type=SNOWFLAKE

5、添加测试类

@Resource
    private BOrderRepository bOrderRepository;


    @Test
    @Repeat(100)// 重复100次·
    public void testShardingBOrder(){
        Random random = new Random();
        int companyId = random.nextInt(10);
        BOrder order = new BOrder();
        order.setDel(false);
        order.setCompanyId(companyId);
        order.setPositionId(3242342);
        order.setUserId(2222);
        order.setPublishUserId(1111);
        order.setResumeType(1);
        order.setStatus("AUTO");
        order.setCreateTime(new Date());
        order.setOperateTime(new Date());
        order.setWorkYear("2");
        order.setName("lagou");
        order.setPositionName("Java");
        order.setResumeId(23233);
        bOrderRepository.save(order);
    }

6、效果展示

company_id为偶数的在lagou1库中,而且根据id信息再进一步分表
lagou1库中b_order0表的结果
image.png

lagou1库中b_order1表的结果
image.png

company_id为奇数的在lagou2库中,而且根据id信息再进一步分表
奇数的 company_id又根据id信息分到b_order0或是b_order1中
image.png
image.png