shardingjdbc

原文链接:https://blog.csdn.net/lsqingfeng/article/details/110425971

一、Sharding JDBC简介

二、环境准备

环境准备:
本次案例采用springboot和mybatis-plus进行演示,具体版本如下:
在这里插入图片描述
首先我们执行一下初始化的sql,创建几张表,然后使用mybatis-plus自动生成所需实体和mapper

1. 初始化sql

CREATE database ds0;
use ds0;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for t_address
-- ----------------------------
DROP TABLE IF EXISTS `t_address`;
CREATE TABLE `t_address` (
  `address_id` bigint(20) NOT NULL,
  `address_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order
-- ----------------------------
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=532651227377807361 DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_1
-- ----------------------------
DROP TABLE IF EXISTS `t_order_1`;
CREATE TABLE `t_order_1` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_2
-- ----------------------------
DROP TABLE IF EXISTS `t_order_2`;
CREATE TABLE `t_order_2` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_3
-- ----------------------------
DROP TABLE IF EXISTS `t_order_3`;
CREATE TABLE `t_order_3` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_4
-- ----------------------------
DROP TABLE IF EXISTS `t_order_4`;
CREATE TABLE `t_order_4` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_item
-- ----------------------------
DROP TABLE IF EXISTS `t_order_item`;
CREATE TABLE `t_order_item` (
  `order_item_id` bigint(20) NOT NULL,
  `order_id` bigint(20) DEFAULT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`order_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `user_id` bigint(20) NOT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
SET FOREIGN_KEY_CHECKS = 1;
 
-- ------------第二个库------------------
CREATE database ds1;
use ds1;
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for t_address
-- ----------------------------
DROP TABLE IF EXISTS `t_address`;
CREATE TABLE `t_address` (
  `address_id` bigint(20) NOT NULL,
  `address_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order
-- ----------------------------
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=532651227377807361 DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_1
-- ----------------------------
DROP TABLE IF EXISTS `t_order_1`;
CREATE TABLE `t_order_1` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_2
-- ----------------------------
DROP TABLE IF EXISTS `t_order_2`;
CREATE TABLE `t_order_2` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_3
-- ----------------------------
DROP TABLE IF EXISTS `t_order_3`;
CREATE TABLE `t_order_3` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_4
-- ----------------------------
DROP TABLE IF EXISTS `t_order_4`;
CREATE TABLE `t_order_4` (
  `order_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) DEFAULT NULL,
  `order_code` varchar(255) DEFAULT NULL,
  `address_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_order_item
-- ----------------------------
DROP TABLE IF EXISTS `t_order_item`;
CREATE TABLE `t_order_item` (
  `order_item_id` bigint(20) NOT NULL,
  `order_id` bigint(20) DEFAULT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`order_item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `user_id` bigint(20) NOT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
 
SET FOREIGN_KEY_CHECKS = 1;

2. 项目结构

在这里插入图片描述
其中 bz模块,是用来存放mybatis-plus生成的实体,mapper等文件的, parent模块是管理依赖的,用于其他模块继承的,剩下的几个模块,是分表演示inline策略模式和standard策略模式实现分库分表的。 两个策略都分别给出了yml配置方式和java config配置方式。

3. parent依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>shardingjdbc-sample</artifactId>
        <groupId>cn.cestc</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
 
    <artifactId>sharding-parent</artifactId>
    <packaging>pom</packaging>
 
 
    <properties>
        <java.version>1.8</java.version>
        <spring.boot.version>2.2.5.RELEASE</spring.boot.version>
        <action.version>1.0.0</action.version>
 
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
        <lombok.version>1.18.8</lombok.version>
        <mybatis-plus.version>3.3.1.tmp</mybatis-plus.version>
        <mysql.connector.version>8.0.17</mysql.connector.version>
        <modelmapper.version>2.3.0</modelmapper.version>
        <shardingsphere.version>4.1.1</shardingsphere.version>
    </properties>
 
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.connector.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <!-- shardingsphere -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
        <!-- for spring namespace -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
    </dependencies>
 
    <build>
        <pluginManagement>
            <plugins>
                <!--编译打包生成源码文档需要的plugins-->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.1.2</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.1.0</version>
                    <configuration>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
 
                <!--spring-boot web 项目打jar包插件(jar包里面包含依赖的jar)-->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring.boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

项目脚手架代码已上传到git: https://github.com/lsqingfeng/sharding-staging.git

这里边只是一个架子,还没有分库分表的实现

好了这几步准备好之后,就可以开始我们的实战了,这一步大家只需要准备好依赖,parent,biz模块即可。后边我们会逐个演示 inline-yml, inline-java, stardard-yml, stard-java 两个策略,两个配置方式的实现。

三、shardingJdbc专题系列(三)之Inline策略分库

1. 需求分析

我们采用最简单的 inline行内表达式策略,通过yml文件中几行简单的配置,来实现一个简单的分库操作。分库的策略是这样的,我们向订单表中插入10条数据,订单表中有订单id和用户id, 订单id我们采用雪花id的生成算法,用户id采用自增的方式,我们又两个库,ds0和ds1, 然后 userId%2, 匹配到不同库中,比如userId是1就保存到ds1库中,userId是2就保存到ds0库中,关于数据库结构,请参看上篇文章,已经给出了sql语句。两个库中都有一个order表。我们通过插入数据,观察效果。

2. 搭建步骤

首先我们创建一个项目module, sharding-inline-yml, (如果已经下载我上篇文章中的脚手架,这个模块已经建好了),依赖sharding-biz模块(该模块是mybatis-plus生成的增删改查), 接下来一步一步来。

添加配置文件

首先添加一个application.yml

server:
  port: 9991
 
spring:
  profiles:
    active: db

在添加一个配置文件 application-db.yml, (主要是为了后边再加一个application-table.yml演示分表)

# 分库
spring:
  shardingsphere:
    datasource:   #数据源配置
      names: ds0,ds1
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/ds0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: root
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/ds1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: root
    sharding:   #分片逻辑
      default-database-strategy:
        inline:
          sharding-column: user_id
          algorithm-expression: ds$->{user_id % 2}
      binding-tables: t_order,t_order_item
      broadcast-tables: t_user
      tables:  #表逻辑
        t_order:
          actual-data-nodes: ds$->{0..1}.t_order
          key-generator:
            column: order_id
            type: SNOWFLAKE
            props:
              worker:
                id: 10
        t_order_item:
          actual-data-nodes: ds$->{0..1}.t_order_item
          key-generator:
            column: order_item_id
            type: SNOWFLAKE
            props:
              worker:
                id: 12

添加Mybatis-plus配置类和启动主类,
在这里插入图片描述
接下来就可以测试了:

package cn.cestc.inline.controller;
 
import cn.cestc.biz.entity.Order;
import cn.cestc.biz.entity.User;
import cn.cestc.biz.service.AddressService;
import cn.cestc.biz.service.OrderItemService;
import cn.cestc.biz.service.OrderService;
import cn.cestc.biz.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Arrays;
import java.util.List;
 
/**
 * @className: TestController
 * @description:
 * @author: sh.Liu
 * @date: 2020-11-15 11:54
 */
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
 
    private final UserService userService;
    private final OrderService orderService;
    private final OrderItemService orderItemService;
    private final AddressService addressService;
 
    public TestController(UserService userService, OrderService orderService, OrderItemService orderItemService, AddressService addressService) {
        this.userService = userService;
        this.orderService = orderService;
        this.orderItemService = orderItemService;
        this.addressService = addressService;
    }
 
 
    @RequestMapping("/user")
    public String testUser(){
        for (int i=1;i<=10; i++) {
            User user = new User();
            user.setUserId(Long.valueOf(i));
            user.setUserName("张三" + i);
            userService.save(user);
        }
        return "sucess";
    }
 
    @RequestMapping("/order")
    public String testOrder(){
        for (int i=1;i<=10; i++) {
            Order order = new Order();
            order.setUserId(Long.valueOf(i));
            order.setOrderCode("acb"+ i);
            order.setAddressId(String.valueOf(i));
            orderService.save(order);
        }
        return "sucess";
    }
 
    @RequestMapping("/listOrder")
    public Object testListOrder(){
        List<Order> list = orderService.list(new LambdaQueryWrapper<Order>().in(Order::getUserId, Arrays.asList(1,2,3,4,5)).orderByAsc(Order::getUserId));
        return list;
    }
 
 
}

浏览器调用 localhost:9991/test/order, 查看Order表,发现
在这里插入图片描述
在这里插入图片描述
就这样数据就根据userId的值分散到了不同的库中。

3. 配置分析

那么这个规则是如何生效的呢,其实先秒尽在配置文件当中:
在这里插入图片描述
最关键的就是图上的三个红框。

首先配置两个数据源,ds0,ds1,

然后配置的是分库策略: 分片列是 user_id, 就是根据这列数据做分片, 算法表达式:

ds$->{user_id % 2} ,这个应该比较好理解,根据user_id 对2取余结果,计算存入到那个库中,

t_order表的真实表,

ds$->{0..1}.t_order。

存储没问题了之后,也可以测试一下查询,通过查询列表看得到的结果。 要注意,只支持 = 和 in

四、shardingJdbc专题系列(四)之Inline策略分表

上篇文章我们演示了使用sharding-jdbc进行分库操作的一个小案例, 采用的是inline模式,也就是在yml配置文件中,通过配置分片算法表达式,来进行分片,也简单体验了一下。其实相对来讲还是比较简单的,这些配置也不用背下来,大家只要做好笔记,用的时候,能够根据自己的业务进行套用就行了。当然如果怕记不住,欢迎关注我,或者收藏我的文章,用的时候过来翻翻就可以了。

那么本篇文章我们接着上篇文章继续,来演示一下更常用的分表操作。为什么说分表更常用呢,因为一旦跨库,就需要解决分布式事务的问题,所以很多人不想徒增麻烦,甚至是分库后,可能导致的唯一id一致等问题,都是很头疼的。接下来进入分表。分表一般都是在一个库里进行操作。会有结构一致的表, 比如 t_order_1, t_order_2, 通过第一节的概念我们提到过,这些表叫做真实表, 他们结构一致, t_order是他们的逻辑表,当然逻辑表是可以不存在的。只是真实表结构的一个总称,并且我们进行查询的时候,只需要写 select * from t_order就行了, shardingJdbc会自动帮助我们去真实表中查询,并整合结果。

好的环境搭建:

我们还是在上篇文章的项目下继续展开,上篇文章已经给出了代码的脚手架。下载下来按照的步骤执行,就能够运行起来。

首先我们还是在 sharding-inline-yml的module下执行, 在resources 资源目录下重新添加一个配置文件 application-table.yml, 用于添加分表的配置,内容如下:

#分表
spring:
  shardingsphere:
    datasource:   #数据源配置
      names: ds0
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/ds0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
        username: root
        password: root
    # 分表配置
    sharding:
      default-table-strategy:
        inline:
          sharding-column: user_id
          algorithm-expression: t_order_${user_id % 4 + 1}
      # 配置广播表
      broadcast-tables: t_user
      binding-tables: t_order,t_order_item
      tables:
        t_order:
          actual-data-nodes: ds0.t_order_$->{1..4}
          key-generator:
            column: order_id
            type: SNOWFLAKE
            props:
              worker:
                id: 123
          table-strategy:
            inline:
              sharding-column: user_id
              algorithm-expression: t_order_${user_id % 4 + 1}

这里可以看到,这次的数据源,我们只用了一个ds0,相当于只在这一个库中操作即可。主要看分表的配置: 首先是有一个默认的分表策略,还配置了一个广播表,和绑定表。广播表其实主要在分库的时候用,被配置成广播表的表,在插入的时候,会在多个分片(库)中同时插入一份。 比如一些字段表,或者配置表,在跨库时关联操作不方便,配置成广播表,各个库里就会都有一份内容完成一样。

tables下面就是对表的操作。不同的表可以配置不同的分片算法,建议所以需要分片的表,都要在下面配置,不分片的都配置成广播表。

我们这里只配了t_order表,当然还可以继续配置其他表。我们表的怎是节点表达式是: ds0.t_order_$->{1…4}

代表真实表为 t_order_1, t_order_2, t_order_3, t_order4, 那么到底是存到哪张表里呢,有下面的table-strategy, 表策略决定: 表策略首先给出inline, 代表使用inline策略:

分片列为: user_id

分片算法表达式: t_order_${user_id %4 +1} 根据user_id 对4取模后加1, 结果肯定格式1-4,来计算到底插入哪张表中。

好了,但是别忘了,在application.yml配置文件中指定使用application-table.yml的配置文件。

spring:
    profiles:
        active: table

然后继续执行主类,启动程序。 访问: localhost:9991/test/order, 向order中插入10条数据,user_id 从1到10;去库中观察结果,此时所有插入的数据都在ds0库中,分布在不同的表中;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
好了很简单的分表就这样完成了。 你get到了么。

说一下大家执行的流程,只需要下载我篇文章的脚手架,然后导入数据库脚本,把配置文件按照文章中的步骤粘贴进去,就可以直接运行了。无需任何其他操作。

另外结合这两篇文章,大家可以测试一下同时分库分表应该怎么做,其实就是配置一下表达式就行了,把两篇文章结合一下即可。

好了这篇文章就到这了,下篇文章我们讲下,如果不想使用yml配置文件,想用java config的方式实现上述功能,代码应该怎么写。

五、shardingJdbc专题系列(五)之Inline策略 java config 实现方式

前面几篇文章我们都是通过yml配置文件的方式,简单实现了 inline模式下的分库分表。 通过yml的方式,我们需要在配置文件中配置数据源和分库分表的策略表达式。那么如果我不想在配置文件中写如此冗长的配置,能否采用java config 的方式实现呢。肯定是可以的。

本篇文章我们就来介绍通过java config的方式来重新实现inline模式下的分库分表。本次代码案例我们在git脚手架里的 sharding-inline-java 的module下进行。(git地址参看第一篇文章)

首先还是先依赖 sharding-biz, 主要是配置文件。

首先在config包下创建 MybatisPlusConfig 配置类,内容如下; (注意:有一个ConditionOnBean注解,用来限制类的加载顺序,防止出错)

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "cn.cestc.biz.mapper")
@ConditionalOnBean(value= DataSource.class)
public class MybatisPlusConfig {
  @Bean
  public PaginationInterceptor paginationInterceptor() {
      PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
      paginationInterceptor.setLimit(-1);
      return paginationInterceptor;
  }
}

第二步,添加一个 shardingJdbc的配置类,用来替换原来的yml

import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import org.apache.shardingsphere.spring.boot.util.DataSourceUtil;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
 
/**
 * @className: ShardingDataSourceConfiguration
 * @description:
 * @author: sh.Liu
 * @date: 2020-11-03 19:23
 */
@Configuration
@MapperScan(basePackages = "cn.cestc.biz.mapper")
public class ShardingDataSourceConfiguration {
 
    @Bean("shardingDataSource")
    public DataSource getShardingDataSource() throws SQLException, ReflectiveOperationException {
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        // 广播表
        List<String> broadcastTables = new LinkedList<>();
        broadcastTables.add("t_user");
        broadcastTables.add("t_address");
        shardingRuleConfig.setBroadcastTables(broadcastTables);
 
        // 默认策略
        shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds0"));
        shardingRuleConfig.setDefaultTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "t_order_${user_id % 4 + 1}"));
        // 获取user表的分片规则配置
        TableRuleConfiguration userInfoTableRuleConfiguration = getUserInfoTableRuleConfiguration();
 
        shardingRuleConfig.getTableRuleConfigs().add(userInfoTableRuleConfiguration);
        Properties props = new Properties();
        props.put("sql.show", "true");
        return ShardingDataSourceFactory.createDataSource(createDataSourceMap(), shardingRuleConfig, props);
    }
 
    /**
     * 配置真实数据源
     * @return 数据源map
     */
    private Map<String, DataSource> createDataSourceMap() throws ReflectiveOperationException {
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        Map<String, Object> dataSourceProperties = new HashMap<>();
        dataSourceProperties.put("DriverClassName", "com.mysql.jdbc.Driver");
        dataSourceProperties.put("jdbcUrl", "jdbc:mysql://localhost:3306/ds0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8");
        dataSourceProperties.put("username", "root");
        dataSourceProperties.put("password", "root");
 
        DataSource dataSource1 = DataSourceUtil.getDataSource("com.zaxxer.hikari.HikariDataSource", dataSourceProperties);
 
        Map<String, Object> dataSourceProperties2 = new HashMap<>();
        dataSourceProperties2.put("DriverClassName", "com.mysql.jdbc.Driver");
        dataSourceProperties2.put("jdbcUrl", "jdbc:mysql://localhost:3306/ds1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8");
        dataSourceProperties2.put("username", "root");
        dataSourceProperties2.put("password", "root");
 
        DataSource dataSource2 = DataSourceUtil.getDataSource("com.zaxxer.hikari.HikariDataSource", dataSourceProperties2);
 
        dataSourceMap.put("ds0",dataSource1);
        dataSourceMap.put("ds1",dataSource2);
        return dataSourceMap;
    }
 
    /**
     * 配置user表的分片规则
     *
     * @return ser表的分片规则配置对象
     */
    private TableRuleConfiguration getUserInfoTableRuleConfiguration() {
        // 为user表配置数据节点
        TableRuleConfiguration ruleConfiguration = new TableRuleConfiguration("t_order", "ds0.t_order_$->{1..4}");
        // 设置分片键
        String shardingKey = "user_id";
        // 为user表配置分库分片策略及分片算法
        ruleConfiguration.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration(shardingKey, "ds$->{user_id % 2}"));
        // 为user表配置分表分片策略及分片算法
        ruleConfiguration.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration(shardingKey, "t_order_${user_id % 4 + 1}"));
        ruleConfiguration.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "order_id"));
        return ruleConfiguration;
    }
}

这个类中,配置了数据源的集合,同时在getUserInfoTableRuleConfiguration 方法中配置了order表的分库分表策略,和之前yml文件中的配置都是对应的,如果有多个表,添加多个方法,在getShardingDataSource 方法中添加(add) 多个策略即可。

最关键的是启动类,需要排除一个类 @SpringBootApplication(exclude = {SpringBootConfiguration.class}), 注意的是 SpringBootConfiguration要选择的是 shardingjdbc包下面的这个类:代码如下

import org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
/**
 * @className: ShardingInlineJavaApplication
 * @description:
 * @author: sh.Liu
 * @date: 2020-11-15 10:57
 */
@SpringBootApplication(exclude = {SpringBootConfiguration.class})
public class ShardingInlineJavaApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShardingInlineJavaApplication.class, args);
    }
}

好了,万事具备,接下来写一个测试的Controller, 测试一下分库分表的策略是否生效即可。

关于inline模式的分库分表到这里就告一段落了,在这一部分中,我们详细介绍了inline模式如何分库,如何分表,以及如何使用java config 实现。 下一部分我们重点研究下一种策略, standard标准策略的分库分表。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值