Configuration de la sous-table de la sous-base de données ShardingSphere (SpringBoot + mybatis + mysql)

1. Qu'est-ce que ShardingSphere

Positionné comme un framework Java léger, il fournit des services supplémentaires dans la couche JDBC de Java. Il utilise le client pour se connecter directement à la base de données et fournit des services sous la forme de packages jar sans déploiement ni dépendances supplémentaires. Il peut être compris comme une version améliorée du pilote JDBC et est entièrement compatible avec JDBC et divers frameworks ORM. Il se compose de trois produits indépendants : Sharding-JDBC, Sharding-Proxy et Sharding-Sidecar (prévu). Ils fournissent tous des fonctions standardisées de partage de données, de transactions distribuées et de gouvernance de base de données.

2. Scénarios d'application

Avec la croissance des affaires, un système de base de données unique ne peut souvent pas répondre aux scénarios d'application de données Internet massives et rencontre des goulots d'étranglement en termes de performances, de disponibilité, d'exploitation et de maintenance. Afin de résoudre ce problème, le middleware d'expansion horizontale et verticale de la base de données (sous-base de données et sous-table) est également réalisé pour répondre à des besoins similaires. Les intergiciels communs pour la sous-base de données et la sous-table incluent MyCat, ShardingSphere et le service de base de données distribué DRDS d'Alibaba. ShardingSphere est un ensemble de middleware de base de données distribuée open source.À l'heure actuelle, une introduction détaillée à l'opération de configuration de la sous-base de données et de la sous-table de ShardingSphere est basée sur un exemple basé sur springBoot + mybatis + mysql.

3. Processus de mise en œuvre

1. Préparer l'environnement de la base de données

1. Installez d'abord deux bases de données MySql

(leurs ports sont respectivement 3306 et 3307), veuillez vous référer ici pour la méthode de création .

2. Créer des bases de données dans les deux bases de données séparément

CREATE DATABASE shardingsphere;

3. Créez deux tables dans deux bases de données

DROP TABLE IF EXISTS `t_user_0`;
CREATE TABLE `t_user_0`  (
  `user_id` bigint(32) NOT NULL COMMENT '主键',
  `id_number` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '身份证号码',
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
  `age` int(4) NULL DEFAULT NULL COMMENT '年龄',
  `gender` int(2) NULL DEFAULT 1 COMMENT '性别:1-男;2-女',
  `birth_date` date NULL DEFAULT NULL COMMENT '出生日期',
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Compact;

DROP TABLE IF EXISTS `t_user_1`;
CREATE TABLE `t_user_1`  (
  `user_id` bigint(32) NOT NULL COMMENT '主键',
  `id_number` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '身份证号码',
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
  `age` int(4) NULL DEFAULT NULL COMMENT '年龄',
  `gender` int(2) NULL DEFAULT 1 COMMENT '性别:1-男;2-女',
  `birth_date` date NULL DEFAULT NULL COMMENT '出生日期',
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Compact;

2. Mise en œuvre du code

1. Créer un système springBoot

(L'outil IDE utilisé dans cet article est IntelliJ IDEA 2019.2 x64, veuillez le rechercher et le créer sur Internet pour le processus spécifique), et le nom du système est shardingsphere. Commencez par écrire le fichier pom.xml de maven. La version utilisée par shardingSphere ici est la 3.1.0.

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.teamo</groupId>
    <artifactId>shardingsphere</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>shardingsphere</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.shardingsphere</groupId>
            <artifactId>sharding-jdbc-core</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.5.13</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
            <version>5.1.32</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. Écrivez le fichier de configuration application.yml

Ici, deux sources de données ds0 et ds1 sont principalement configurées, qui correspondent respectivement aux deux bases de données créées au départ.

server:
  port: 8090
spring:
  datasource:
    type-aliases-package: com.teamo.shardingsphere.mapper
    mapper-locations: classpath:/mapper/*.xml
    ds0:
      url: jdbc:mysql://localhost:3306/shardingsphere?useUnicode=true&characterEncoding=utf-8&useSSL=true
      username: root
      password:
      driver-class-name: com.mysql.jdbc.Driver
      initialSize: 2                                #初始化大小
      maxWait: 6000                                 #获取连接时最大等待时间,单位毫秒。
      min-idle: 5                                   # 数据库连接池的最小维持连接数
      maxActive: 20                                  # 最大的连接数
      initial-size: 5                               # 初始化提供的连接数
      max-wait-millis: 200                       # 等待连接获取的最大超时时间
      type: com.alibaba.druid.pool.DruidDataSource
    ds1:
      url: jdbc:mysql://localhost:3307/shardingsphere?useUnicode=true&characterEncoding=utf-8&useSSL=true
      username: root
      password:
      driver-class-name: com.mysql.jdbc.Driver
      initialSize: 2                                #初始化大小
      maxWait: 6000                                 #获取连接时最大等待时间,单位毫秒。
      min-idle: 5                                   # 数据库连接池的最小维持连接数
      maxActive: 20                                  # 最大的连接数
      initial-size: 5                               # 初始化提供的连接数
      max-wait-millis: 200                          # 等待连接获取的最大超时时间
      type: com.alibaba.druid.pool.DruidDataSource
mybatis:
	configuration:
		map-underscore-to-camel-case: true
	type-aliases-package: com.teamo.shardingsphere.model
	mapper-locations: classpath:mapper/*.xml

3. Créez la classe de configuration de source de données DataSourceConfig.java de shardingSphere

Une attention particulière doit être portée à la méthode userRuleConfig, qui consiste à définir les règles de sous-base de données et de sous-table pour la table t_user.

3.1. La table t_user crée quatre tables au total, qui sont ds0_t_user0, ds0_t_user1, ds1_t_user0 et ds1_t_user1.
tableRuleConfig.setActualDataNodes ("ds0.t_user_0,ds0.t_user_1,ds1.t_user_0,ds1.t_user_1 ") );
3.2. La table t_user utilise la clé primaire user_id comme clé de sous-base de données et clé de sous-table
//set t_user sub- règles de base de données
tableRuleConfig.setDatabaseShardingStrategyConfig(
new StandardShardingStrategyConfiguration("user_id", new DatabaseShardingAlgorithm()));
//Définir les règles de partition de table t_user
tableRuleConfig.setTableShardingStrategyConfig(
new StandardShardingStrategyConfiguration("user_id", new IdCommonShardingAlgorithm()));
où la classe DatabaseShardingAlgorithm est La classe de bibliothèque, la classe IdCommonShardingAlgorithm est divisée en classes Table, elles implémentent toutes l'interface PreciseShardingAlgorithm, et implémentent la logique de sous-base de données et de sous-table correspondante dans la méthode d'interface. Pour plus de détails, veuillez vous référer au contenu spécifique de ces deux classes.

package com.teamo.shardingsphere.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.teamo.shardingsphere.dbstrategy.DatabaseShardingAlgorithm;
import com.teamo.shardingsphere.dbstrategy.GenderTableShardingAlgorithm;
import com.teamo.shardingsphere.dbstrategy.IdCommonShardingAlgorithm;
import io.shardingsphere.api.config.rule.ShardingRuleConfiguration;
import io.shardingsphere.api.config.rule.TableRuleConfiguration;
import io.shardingsphere.api.config.strategy.InlineShardingStrategyConfiguration;
import io.shardingsphere.api.config.strategy.StandardShardingStrategyConfiguration;
import io.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
import lombok.Data;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/***
 * @author teamo
 * @date 2022-03-18
 */
@Configuration
@Data
public class DataSourceConfig {
    
    
    @Value("${spring.datasource.type-aliases-package}")
    private String typeAliasesPackage;

    @Value("${spring.datasource.mapper-locations}")
    private String mapperLocation;

    @Value("${spring.datasource.ds0.url}")
    private String url0;
    @Value("${spring.datasource.ds0.username}")
    private String userName0;
    @Value("${spring.datasource.ds0.password}")
    private String password0;
    @Value("${spring.datasource.ds0.driver-class-name}")
    private String driverClassName0;
    @Value("${spring.datasource.ds0.type}")
    private String dsType0;

    @Value("${spring.datasource.ds1.url}")
    private String url1;
    @Value("${spring.datasource.ds1.username}")
    private String userName1;
    @Value("${spring.datasource.ds1.password}")
    private String password1;
    @Value("${spring.datasource.ds1.driver-class-name}")
    private String driverClassName1;
    @Value("${spring.datasource.ds1.type}")
    private String dsType1;

    /**
     * 获取数据源Map
     */
    private Map<String, DataSource> getDatasourceMap() {
    
    
        // 真实数据源map
        Map<String, DataSource> dataSourceMap = new HashMap<String, DataSource>(2);
        // 配置第一个数据源
        DruidDataSource dataSource0 = new DruidDataSource();
        dataSource0.setDriverClassName(driverClassName0);
        dataSource0.setUrl(url0);
        dataSource0.setUsername(userName0);
        dataSource0.setPassword(password0);
        dataSource0.setMinIdle(5);
        dataSource0.setMaxActive(20);
        dataSource0.setInitialSize(5);
        dataSource0.setMaxWait(6000);
        dataSourceMap.put("ds0", dataSource0);

        // 配置第二个数据源
        DruidDataSource dataSource1 = new DruidDataSource();
        dataSource1.setDriverClassName(driverClassName1);
        dataSource1.setUrl(url1);
        dataSource1.setUsername(userName1);
        dataSource1.setPassword(password1);
        dataSource1.setMinIdle(5);
        dataSource1.setMaxActive(20);
        dataSource1.setInitialSize(5);
        dataSource1.setMaxWait(6000);
        dataSourceMap.put("ds1", dataSource1);
        return dataSourceMap;
    }

    @Bean
    public Filter statFilter() {
    
    
        StatFilter filter = new StatFilter();
        filter.setSlowSqlMillis(5000);
        filter.setLogSlowSql(true);
        filter.setMergeSql(true);
        return filter;
    }

    @Bean
    public ServletRegistrationBean statViewServlet() {
    
    
        //创建servlet注册实体
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        //设置ip白名单
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        //设置控制台管理用户
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        //是否可以重置数据
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    /****
     * sharding-jdbc-core(3.1.0)
     * @return
     * @throws SQLException
     */
    @Bean("dataSource")
    @Primary
    public DataSource dataSource() throws SQLException {
    
    
        // 配置真实数据源
        Map<String, DataSource> dataSourceMap = getDatasourceMap();
        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        // 设置全局默认库
        //fshardingRuleConfig.setDefaultDataSourceName("ds0");
        shardingRuleConfig.getTableRuleConfigs().add(userRuleConfig());
        //设置默认数据源分片策略
        shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new IdCommonShardingAlgorithm()));
        Properties p = new Properties();
        p.setProperty("sql.show",Boolean.TRUE.toString());
        // 获取数据源对象
        DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new ConcurrentHashMap(), p);
        return dataSource;
    }

    /**
     * 需要手动配置事务管理器
     * @param dataSource
     * @return
     */
    @Bean
    public DataSourceTransactionManager transactitonManager(@Qualifier("dataSource") DataSource dataSource){
    
    
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
    
    
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        return bean.getObject();
    }

    @Bean("sqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
    
    
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    private TableRuleConfiguration userRuleConfig() {
    
    
        TableRuleConfiguration tableRuleConfig = new TableRuleConfiguration();
        tableRuleConfig.setLogicTable("t_user");
        tableRuleConfig.setActualDataNodes("ds0.t_user_0,ds0.t_user_1,ds1.t_user_0,ds1.t_user_1");
        tableRuleConfig.setKeyGeneratorColumnName("user_id");
        tableRuleConfig.setDatabaseShardingStrategyConfig(
                new StandardShardingStrategyConfiguration("user_id", new DatabaseShardingAlgorithm()));
        tableRuleConfig.setTableShardingStrategyConfig(
                new StandardShardingStrategyConfiguration("user_id", new IdCommonShardingAlgorithm()));
        return tableRuleConfig;
    }
}

4. Classe de règles de la sous-base de données Table t_user DatabaseShardingAlgorithm

La logique de la sous-base de données est la valeur de la clé primaire user_id et la valeur des 2 restants pour déterminer la sélection de la base de données. Par exemple,
si une donnée est actuellement insérée et que la valeur de la clé primaire user_id est 3 , alors (3%2==1) la base de données sélectionne db1

package com.teamo.shardingsphere.dbstrategy;

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection;

/**
 * 数据源分片策略
 * @author teamo
 * @date 2022/3/18
 */
public class DatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    
    
    @Override
    public String doSharding(Collection<String> availableTargetNames,
                             PreciseShardingValue<Long> shardingValue) {
    
    
        long res = 0 ;
         for (String each : availableTargetNames) {
    
    
             res = shardingValue.getValue() ;
             res = res % 2;
             if (each.endsWith(res + "")) {
    
    
                 return each;
             }
         }
         throw new UnsupportedOperationException();
    }
}

5. Règle de sous-table de la table t_user IdCommonShardingAlgorithm

La logique de division de table consiste à prendre la valeur de la clé primaire user_id de la table t_user, la longueur de user_id est len, prendre la somme entre 0 et len-1 chiffres, et utiliser la valeur obtenue par la valeur somme %2 pour déterminer quelle table choisir. Exemple 1
: En cours d'insertion d'une donnée, la valeur de user_id est 11, puis la longueur de user_id est 2, un seul chiffre entre 0-1 est 1, puis 1%2=1, donc la valeur sélectionnée la bibliothèque est t_user1 Exemple 2 : Insertion en cours d'un
élément Data, la valeur de user_id est 131, puis la longueur de user_id est 3, le nombre entre 0-2 est 1 et 3, puis (1+3)%2=0, donc la bibliothèque sélectionnée est t_user0

package com.teamo.shardingsphere.dbstrategy;

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;

import java.util.Collection;

public class IdCommonShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
    
    
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
    
    
        String target = availableTargetNames.stream().findFirst().get();
        for (String tableName : availableTargetNames) {
    
    
            if (tableName.endsWith(idToTableSuffix(shardingValue.getValue()))) {
    
    
                target = tableName;
            }
        }
        return target;
    }
    private String idToTableSuffix(Long id) {
    
    
        String idStr = String.valueOf(id);
        int total = 0;
        for(int i=0;i <idStr.length()-1; i++){
    
    
            Integer num = Integer.parseInt(idStr.substring(i,i+1));
            total+=num;
        }
        return String.valueOf(total % 2);
    }
}

6. Classe modèle

package com.teamo.shardingsphere.model;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    
    
    private Long userId;
    private String idNumber;
    private String name;
    private Integer age;
    private Integer gender;
    private Date birthDate;
    private static final long serialVersionUID = 1L;
    public Long getUserId() {
    
    
        return userId;
    }
    public void setUserId(Long userId) {
    
    
        this.userId = userId;
    }
    public String getIdNumber() {
    
    
        return idNumber;
    }
    public void setIdNumber(String idNumber) {
    
    
        this.idNumber = idNumber == null ? null : idNumber.trim();
    }
    public String getName() {
    
    
        return name;
    }
    public void setName(String name) {
    
    
        this.name = name == null ? null : name.trim();
    }
    public Integer getAge() {
    
    
        return age;
    }
    public void setAge(Integer age) {
    
    
        this.age = age;
    }
    public Integer getGender() {
    
    
        return gender;
    }
    public void setGender(Integer gender) {
    
    
        this.gender = gender;
    }
    public Date getBirthDate() {
    
    
        return birthDate;
    }
    public void setBirthDate(Date birthDate) {
    
    
        this.birthDate = birthDate;
    }
}

7. Classe Dao

package com.teamo.shardingsphere.mapper;

import com.teamo.shardingsphere.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Mapper
@Component
public interface UserMapper  {
    
    
    int deleteByPrimaryKey(Long userId);
    int insert(User record);
    int insertSelective(User record);
    User selectByPrimaryKey(Long userId);
    int updateByPrimaryKeySelective(User record);
    int updateByPrimaryKey(User record);
    List<User> selectAll(int start, int limit);
}

8. fichier de configuration du mappeur (fichier .xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.teamo.shardingsphere.mapper.UserMapper">
  <resultMap id="BaseResultMap" type="com.teamo.shardingsphere.model.User">
    <id column="user_id" jdbcType="BIGINT" property="userId" />
    <result column="id_number" jdbcType="VARCHAR" property="idNumber" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="age" jdbcType="INTEGER" property="age" />
    <result column="gender" jdbcType="INTEGER" property="gender" />
    <result column="birth_date" jdbcType="DATE" property="birthDate" />
  </resultMap>
  <sql id="Base_Column_List">
    user_id, id_number, name, age, gender, birth_date
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from t_user
    where user_id = #{userId,jdbcType=BIGINT}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from t_user
    where user_id = #{userId,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.teamo.shardingsphere.model.User">
    insert into t_user (user_id, id_number, name,
      age, gender, birth_date
      )
    values (#{userId,jdbcType=BIGINT}, #{idNumber,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
      #{age,jdbcType=INTEGER}, #{gender,jdbcType=INTEGER}, #{birthDate,jdbcType=DATE}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.teamo.shardingsphere.model.User" useGeneratedKeys="true" keyProperty="userId">
    insert into t_user
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="userId != null">
        user_id,
      </if>
      <if test="idNumber != null">
        id_number,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="age != null">
        age,
      </if>
      <if test="gender != null">
        gender,
      </if>
      <if test="birthDate != null">
        birth_date,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="userId != null">
        #{userId,jdbcType=BIGINT},
      </if>
      <if test="idNumber != null">
        #{idNumber,jdbcType=VARCHAR},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null">
        #{age,jdbcType=INTEGER},
      </if>
      <if test="gender != null">
        #{gender,jdbcType=INTEGER},
      </if>
      <if test="birthDate != null">
        #{birthDate,jdbcType=DATE},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.teamo.shardingsphere.model.User">
    update t_user
    <set>
      <if test="idNumber != null">
        id_number = #{idNumber,jdbcType=VARCHAR},
      </if>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null">
        age = #{age,jdbcType=INTEGER},
      </if>
      <if test="gender != null">
        gender = #{gender,jdbcType=INTEGER},
      </if>
      <if test="birthDate != null">
        birth_date = #{birthDate,jdbcType=DATE},
      </if>
    </set>
    where user_id = #{userId,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.teamo.shardingsphere.model.User">
    update t_user
    set id_number = #{idNumber,jdbcType=VARCHAR},
      name = #{name,jdbcType=VARCHAR},
      age = #{age,jdbcType=INTEGER},
      gender = #{gender,jdbcType=INTEGER},
      birth_date = #{birthDate,jdbcType=DATE}
    where user_id = #{userId,jdbcType=BIGINT}
  </update>
  <select id="selectAll"  resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from t_user
    order by user_id
    limit #{start}, #{limit}
  </select>
</mapper>

9. Classe de service

Voici un exemple de démonstration, il n'y a aucun moyen d'implémenter la classe strictement selon l'interface

package com.teamo.shardingsphere.Service;

import com.teamo.shardingsphere.mapper.*;
import com.teamo.shardingsphere.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class BussinessService {
    
    
    @Autowired
    private UserMapper userMapper;
    @Transactional
    public void saveUser(User user) {
    
    
        userMapper.insertSelective(user);
    }

    public List<User> selectAllUser(int start, int limit ){
    
    
        return userMapper.selectAll(start, limit);
    }
}

10. Classe contrôleur

La classe Controller écrit deux méthodes, l'une est la méthode d'écriture des données de la table t_user (en utilisant la boucle for pour écrire 40 enregistrements et enregistrements), et l'autre est la méthode d'interrogation de la table t_user et de la pagination, le but est de détecter les données écrites dans la table t_user et s'il faut fonctionner selon les règles de sous-base de données et de sous-table que nous avons définies lors de la lecture des données.

package com.teamo.shardingsphere.controller;

import cn.hutool.core.date.DateUtil;
import com.teamo.shardingsphere.Service.BussinessService;
import com.teamo.shardingsphere.model.*;
import com.teamo.shardingsphere.util.SnowflakeKeyGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
public class BussinessController {
    
    
    @Autowired
    private BussinessService bussinessService;

    @GetMapping("/buss/create")
    public String create() {
    
    
        for (int i = 1; i <= 40; i++) {
    
    
            User user = new User();
            //user.setUserId(snowflakeKeyGenerator.nextId());
            user.setUserId(Long.parseLong((i)+""));
            user.setName("王小晖" + i);
            user.setGender(GenderEnum.MALE.getCode());
            user.setAge(20 + i);
            user.setBirthDate(DateUtil.parseDate("1989-08-16"));
            user.setIdNumber("4101231989691" + i);
            bussinessService.saveUser(user);
        }
        return "成功";
    }

    @GetMapping("/buss/allUser")
    public List<User> findAllUser(int start, int limit){
    
    
        return bussinessService.selectAllUser(start, limit);
    }
}

11. Classe de démarrage SpringBoot

package com.teamo.shardingsphere;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude={
    
    DataSourceAutoConfiguration.class})
public class ShardingsphereApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(ShardingsphereApplication.class, args);
    }
}

À ce stade, l'ensemble du système de démonstration est écrit

3. Exécutez le test

1. Démarrez le système

Cliquez avec le bouton droit sur la classe de démarrage pour démarrer le système de démonstration

insérez la description de l'image ici

2. Test d'insertion de données

Une fois le système démarré avec succès, ouvrez le navigateur et entrez http://localhost:9090/buss/create dans la barre d'adresse. Lorsque la page s'affiche avec succès, cela indique que la méthode d'insertion des données dans la table t_user est exécutée avec succès.
insérez la description de l'image ici
Connectez-vous ensuite à la base de données et vérifiez l'insertion de l'entrée dans la bibliothèque
ds0 de la table de base de données : Extrayez le troisième enregistrement des tables t_user0 et t_user1 de la bibliothèque ds0 pour effectuer une vérification logique du
troisième enregistrement de t_user0 user_id=6
La valeur de user_id de la règle de sous-base de données %2==0, donc la longueur de la valeur user_id de la sous-base de données à la
règle de sous-table ds0 est 1, et il n'y a pas de nombre entre 0 et (1-1), qui est 0 , donc la sous-table est divisée en t_user0, donc l'enregistrement avec
user_id=6 sera inséré Dans la bibliothèque ds0, dans la table t_user0, la vérification est correcte

L'user_id=14 du troisième enregistrement de t_user1
est la valeur de user_id dans la règle de sous-base de données %2==0, donc
la longueur de la valeur user_id de la sous-base de données à la règle de sous-table ds0 est 2, et la valeur entre [0 et (2-1)) est 1, appuyez sur La somme des longueurs est 1, donc la table est divisée en t_user1,
donc l'enregistrement avec user_id=6 sera inséré dans la bibliothèque ds0, table t_user1, et la vérification est correcte
insérez la description de l'image ici

insérez la description de l'image ici
bibliothèque ds1 bibliothèque
ds1 : extrayez le 5e enregistrement des tables t_user0 et t_user1 de la bibliothèque ds0 pour la vérification logique de la sous-table de la sous-base de données. User_id=9 du cinquième enregistrement
de t_user0
La valeur de user_id dans la règle de sous-bibliothèque %2 ==1, donc la sous-bibliothèque La longueur de la valeur user_id de la
règle de sous-table ds1 est 1, et il n'y a pas de nombre entre 0 et (1-1), qui est 0, donc la sous-table est assignée à t_user0, donc l'enregistrement avec
user_id=6 sera inséré dans la bibliothèque ds1, la table t_user0 et le calibrage Vérifier correct

Le user_id=19 du 5ème enregistrement de t_user1
est la valeur de user_id de la règle de sous-base de données %2==1, donc la
longueur de la valeur user_id de la sous-base de données vers la règle de sous-table ds1 est 2, et la valeur entre [0 et (2-1)) est 1, appuyez sur La somme des longueurs est 1, donc la table est divisée en t_user1,
donc l'enregistrement avec user_id=6 sera inséré dans la bibliothèque ds1, table t_user1, et la vérification est correcte
insérez la description de l'image ici
insérez la description de l'image ici

3. Test de requête de données

Entrez http://localhost:9090/buss/allUser?start=0&limit=5 dans le navigateur
insérez la description de l'image icipour afficher le journal sql imprimé en arrière-plan. Une fois que le système a analysé les règles de ShardingSphere, le sql réellement envoyé à la base de données est
insérez la description de l'image ici

On peut voir qu'après que ShardingSphere ait effectué des opérations de configuration de sous-base de données et de sous-table, la source de données de la requête à table unique du système sera obtenue à partir de toutes les tables de base de données configurées (dans ce cas, deux bases de données et quatre tables).

4. Résumé

Lorsque nous planifions le système au début, si nous prévoyons que le système peut présenter des risques de performance causés par un stockage de données volumineux, ou pendant le processus d'exploitation et de maintenance, le système constate que le volume de données d'une certaine table dans une certaine entreprise est trop grand pour causer des problèmes de performances. Envisagez d'adopter ShardingSphere. La clé d'une utilisation efficace de ShardingSphere est la détermination et la définition de règles de sous-base de données et de sous-table. La détermination de ces règles doit être déterminée en fonction de la logique de l'activité de requête de la table. Seul un bon paramétrage des règles peut lui faire montrer ses avantages. La règle optimale pour la clé de sous-table de sous-base de données est de diviser les données correspondantes en différentes tables selon l'entreprise, comme la division par unité (la prémisse est que l'entreprise est exercée dans la même unité, et il y a moins d'entreprises unités de passage), Cela aura l'effet désiré.

Je suppose que tu aimes

Origine blog.csdn.net/teamo_m/article/details/123506140
conseillé
Classement