sharding5.0.0分表分库

news2024/12/20 17:44:10

sharding官网参考

https://shardingsphere.apache.org/document/current/cn/overview/

https://shardingsphere.apache.org/document/legacy/4.x/document/cn/features/sharding/use-norms/pagination/

 https://shardingsphere.apache.org/document/legacy/4.x/document/cn/downloads/#%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC

https://shardingsphere.apache.org/document/5.0.0/cn/features/sharding/

优秀文章参考

ShardingSphere-JDBC - YAML 配置 - 《Apache ShardingSphere v5.1.0 中文文档》 - 书栈网 · BookStack

 https://www.cnblogs.com/xfeiyun/p/16185727.html

 ShardingJDBC-5.0.0及4.0.0使用示例_sharding-jdbc 5._红石丶的博客-CSDN博客

引言:

sharding各个版本相对而言不能配置都有差异,而sharding5.0.0.0相对而言是比较新的,网上相关的资料少的可怜,参考了非常多的文章写下demo,供大家参考

集成

1 当前使用shardingsphere-jdbc-core-spring-boot-starter 5.0.0版本

 <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>${dynamic-datasource-spring-boot-starter.version}</version>
        </dependency>
        <!-- 分库分表 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.0.0</version>
        </dependency>

 因为数据源之前框架已经有druild,为了不影响之前的框架数据源配置,增加动态多数据源

package org.jeecg.boot.shardingsphere.config;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.AbstractDataSourceProvider;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;

/**
 * 分库分表数据源配置
 * @author zyf
 */
@Configuration
@AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class, SpringBootConfiguration.class})
public class DataSourceConfiguration {
    /**
     * 分表数据源名称
     */
    public static final String SHARDING_DATA_SOURCE_NAME = "sharding";
    /**
     * 动态数据源配置项
     */
    @Resource
    private DynamicDataSourceProperties dynamicDataSourceProperties;

    @Lazy
    @Resource
    DataSource shardingDataSource;

    /**
     * 将shardingDataSource放到了多数据源(dataSourceMap)中
     * 注意有个版本的bug,3.1.1版本 不会进入loadDataSources 方法,这样就一直造成数据源注册失败
     */
    @Bean
    public DynamicDataSourceProvider dynamicDataSourceProvider() {
        Map<String, DataSourceProperty> datasourceMap = dynamicDataSourceProperties.getDatasource();
        return new AbstractDataSourceProvider() {
            @Override
            public Map<String, DataSource> loadDataSources() {
                Map<String, DataSource> dataSourceMap = createDataSourceMap(datasourceMap);
                // 将 shardingjdbc 管理的数据源也交给动态数据源管理
                dataSourceMap.put(SHARDING_DATA_SOURCE_NAME, shardingDataSource);
                return dataSourceMap;
            }
        };
    }

    /**
     * 将动态数据源设置为首选的
     * 当spring存在多个数据源时, 自动注入的是首选的对象
     * 设置为主要的数据源之后,就可以支持shardingjdbc原生的配置方式了
     *
     * @return
     */
    @Primary
    @Bean
    public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        dataSource.setPrimary(dynamicDataSourceProperties.getPrimary());
        dataSource.setStrict(dynamicDataSourceProperties.getStrict());
        dataSource.setStrategy(dynamicDataSourceProperties.getStrategy());
        dataSource.setProvider(dynamicDataSourceProvider);
        dataSource.setP6spy(dynamicDataSourceProperties.getP6spy());
        dataSource.setSeata(dynamicDataSourceProperties.getSeata());
        return dataSource;
    }
}

 2 项目结构

 

 3 初始化sql


#1按照年月范围分表sql
CREATE TABLE `t_order_2020_6` (
                                  `id` bigint(20) NOT NULL COMMENT '主键',
                                  `name` varchar(20) DEFAULT NULL COMMENT '名称',
                                  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
                                  `user_name` varchar(20) DEFAULT NULL COMMENT '订单所属用户名',
                                  PRIMARY KEY (`id`),
                                  KEY `user_name_index` (`user_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单表';



CREATE TABLE `t_order_item_2020_6` (
                                       `id` bigint(20) NOT NULL COMMENT '主键',
                                       `order_id` bigint(20) DEFAULT NULL COMMENT '订单ID',
                                       `name` varchar(20) DEFAULT NULL COMMENT '名称',
                                       `order_create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
                                       PRIMARY KEY (`id`),
                                       KEY `order_id_index` (`order_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单商品表';



CREATE TABLE `t_order_middle_test` (
  `id` BIGINT(20) NOT NULL COMMENT '主键',
  `order_id` VARCHAR(20) DEFAULT NULL COMMENT '名称',
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='订单中间表测试'

#2按照年范围分表sql
CREATE TABLE `t_order_2022` (
  `id` BIGINT(20) NOT NULL COMMENT '主键',
  `name` VARCHAR(20) DEFAULT NULL COMMENT '名称',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
  `user_name` VARCHAR(20) DEFAULT NULL COMMENT '订单所属用户名',
  PRIMARY KEY (`id`),
  KEY `user_name_index` (`user_name`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='订单表'

CREATE TABLE `t_order_2023` (
  `id` BIGINT(20) NOT NULL COMMENT '主键',
  `name` VARCHAR(20) DEFAULT NULL COMMENT '名称',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
  `user_name` VARCHAR(20) DEFAULT NULL COMMENT '订单所属用户名',
  PRIMARY KEY (`id`),
  KEY `user_name_index` (`user_name`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='订单表'


CREATE TABLE `t_order_item_2022` (
  `id` BIGINT(20) NOT NULL COMMENT '主键',
  `order_id` BIGINT(20) DEFAULT NULL COMMENT '订单ID',
  `name` VARCHAR(20) DEFAULT NULL COMMENT '名称',
  `order_create_time` DATETIME DEFAULT NULL COMMENT '订单创建时间',
  PRIMARY KEY (`id`),
  KEY `order_id_index` (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='订单商品表'



CREATE TABLE `t_order_item_2023` (
  `id` BIGINT(20) NOT NULL COMMENT '主键',
  `order_id` BIGINT(20) DEFAULT NULL COMMENT '订单ID',
  `name` VARCHAR(20) DEFAULT NULL COMMENT '名称',
  `order_create_time` DATETIME DEFAULT NULL COMMENT '订单创建时间',
  PRIMARY KEY (`id`),
  KEY `order_id_index` (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='订单商品表'

CREATE TABLE `sys_log` (
  `id` VARCHAR(32) NOT NULL,
  `log_type` INT(2) DEFAULT NULL COMMENT '日志类型(1登录日志,2操作日志)',
  `log_content` VARCHAR(1000) DEFAULT NULL COMMENT '日志内容',
  `operate_type` INT(2) DEFAULT NULL COMMENT '操作类型',
  `userid` VARCHAR(32) DEFAULT NULL COMMENT '操作用户账号',
  `username` VARCHAR(100) DEFAULT NULL COMMENT '操作用户名称',
  `ip` VARCHAR(100) DEFAULT NULL COMMENT 'IP',
  `method` VARCHAR(500) DEFAULT NULL COMMENT '请求java方法',
  `request_url` VARCHAR(255) DEFAULT NULL COMMENT '请求路径',
  `request_param` LONGTEXT DEFAULT NULL COMMENT '请求参数',
  `request_type` VARCHAR(10) DEFAULT NULL COMMENT '请求类型',
  `cost_time` BIGINT(20) DEFAULT NULL COMMENT '耗时',
  `create_by` VARCHAR(32) DEFAULT NULL COMMENT '创建人',
  `create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
  `update_by` VARCHAR(32) DEFAULT NULL COMMENT '更新人',
  `update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `index_table_userid` (`userid`) USING BTREE,
  KEY `index_logt_ype` (`log_type`) USING BTREE,
  KEY `index_operate_type` (`operate_type`) USING BTREE,
  KEY `index_createtime` (`create_time`) USING BTREE
) ENGINE=MYISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='系统日志表';

CREATE TABLE `sys_log0` (
  `id` varchar(32) NOT NULL,
  `log_type` int(2) DEFAULT NULL COMMENT '日志类型(1登录日志,2操作日志)',
  `log_content` varchar(1000) DEFAULT NULL COMMENT '日志内容',
  `operate_type` int(2) DEFAULT NULL COMMENT '操作类型',
  `userid` varchar(32) DEFAULT NULL COMMENT '操作用户账号',
  `username` varchar(100) DEFAULT NULL COMMENT '操作用户名称',
  `ip` varchar(100) DEFAULT NULL COMMENT 'IP',
  `method` varchar(500) DEFAULT NULL COMMENT '请求java方法',
  `request_url` varchar(255) DEFAULT NULL COMMENT '请求路径',
  `request_param` longtext DEFAULT NULL COMMENT '请求参数',
  `request_type` varchar(10) DEFAULT NULL COMMENT '请求类型',
  `cost_time` bigint(20) DEFAULT NULL COMMENT '耗时',
  `create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `index_table_userid` (`userid`) USING BTREE,
  KEY `index_logt_ype` (`log_type`) USING BTREE,
  KEY `index_operate_type` (`operate_type`) USING BTREE,
  KEY `index_createtime` (`create_time`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='系统日志表';

CREATE TABLE `sys_log1` (
  `id` varchar(32) NOT NULL,
  `log_type` int(2) DEFAULT NULL COMMENT '日志类型(1登录日志,2操作日志)',
  `log_content` varchar(1000) DEFAULT NULL COMMENT '日志内容',
  `operate_type` int(2) DEFAULT NULL COMMENT '操作类型',
  `userid` varchar(32) DEFAULT NULL COMMENT '操作用户账号',
  `username` varchar(100) DEFAULT NULL COMMENT '操作用户名称',
  `ip` varchar(100) DEFAULT NULL COMMENT 'IP',
  `method` varchar(500) DEFAULT NULL COMMENT '请求java方法',
  `request_url` varchar(255) DEFAULT NULL COMMENT '请求路径',
  `request_param` longtext DEFAULT NULL COMMENT '请求参数',
  `request_type` varchar(10) DEFAULT NULL COMMENT '请求类型',
  `cost_time` bigint(20) DEFAULT NULL COMMENT '耗时',
  `create_by` varchar(32) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(32) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `index_table_userid` (`userid`) USING BTREE,
  KEY `index_logt_ype` (`log_type`) USING BTREE,
  KEY `index_operate_type` (`operate_type`) USING BTREE,
  KEY `index_createtime` (`create_time`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='系统日志表';


CREATE TABLE `tb_cust` (
  `cust_id` BIGINT (20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `cust_name` VARCHAR (20) NOT NULL COMMENT '用户名称',
  `branch_id` CHAR(3) NOT NULL COMMENT '分公司',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`cust_id`)
) ENGINE = INNODB AUTO_INCREMENT = 202 DEFAULT CHARSET = utf8 COMMENT = '客户信息表';


CREATE TABLE `tb_cust_fc5` (
  `cust_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `cust_name` VARCHAR(20) NOT NULL COMMENT '用户名称',
  `branch_id` CHAR(3) NOT NULL COMMENT '分公司',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=202 DEFAULT CHARSET=utf8 COMMENT='客户信息表';
CREATE TABLE `tb_cust_fdg` (
  `cust_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `cust_name` VARCHAR(20) NOT NULL COMMENT '用户名称',
  `branch_id` CHAR(3) NOT NULL COMMENT '分公司',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=202 DEFAULT CHARSET=utf8 COMMENT='客户信息表';

CREATE TABLE `tb_cust_fdm` (
  `cust_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `cust_name` VARCHAR(20) NOT NULL COMMENT '用户名称',
  `branch_id` CHAR(3) NOT NULL COMMENT '分公司',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=202 DEFAULT CHARSET=utf8 COMMENT='客户信息表';


CREATE TABLE `tb_cust_fdw` (
  `cust_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `cust_name` VARCHAR(20) NOT NULL COMMENT '用户名称',
  `branch_id` CHAR(3) NOT NULL COMMENT '分公司',
  `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`cust_id`)
) ENGINE=INNODB AUTO_INCREMENT=202 DEFAULT CHARSET=utf8 COMMENT='客户信息表';





CREATE TABLE `t_complex` (
  `order_id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NOT NULL,
  `address_id` BIGINT(20) NOT NULL,
  `city` VARCHAR(32) DEFAULT NULL,
  `status` TINYINT(4) DEFAULT NULL,
  `creator` VARCHAR(32) DEFAULT NULL,
  `create_time` DATETIME DEFAULT NULL,
  `updater` VARCHAR(32) DEFAULT NULL,
  `update_time` DATETIME DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMI;



CREATE TABLE `t_complex_0` (
  `order_id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NOT NULL,
  `address_id` BIGINT(20) NOT NULL,
  `city` VARCHAR(32) DEFAULT NULL,
  `status` TINYINT(4) DEFAULT NULL,
  `creator` VARCHAR(32) DEFAULT NULL,
  `create_time` DATETIME DEFAULT NULL,
  `updater` VARCHAR(32) DEFAULT NULL,
  `update_time` DATETIME DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

CREATE TABLE `t_complex_1` (
  `order_id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NOT NULL,
  `address_id` BIGINT(20) NOT NULL,
  `city` VARCHAR(32) DEFAULT NULL,
  `status` TINYINT(4) DEFAULT NULL,
  `creator` VARCHAR(32) DEFAULT NULL,
  `create_time` DATETIME DEFAULT NULL,
  `updater` VARCHAR(32) DEFAULT NULL,
  `update_time` DATETIME DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

CREATE TABLE `t_complex_2` (
  `order_id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NOT NULL,
  `address_id` BIGINT(20) NOT NULL,
  `city` VARCHAR(32) DEFAULT NULL,
  `status` TINYINT(4) DEFAULT NULL,
  `creator` VARCHAR(32) DEFAULT NULL,
  `create_time` DATETIME DEFAULT NULL,
  `updater` VARCHAR(32) DEFAULT NULL,
  `update_time` DATETIME DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

CREATE TABLE `t_complex_3` (
  `order_id` BIGINT(20) NOT NULL,
  `user_id` BIGINT(20) NOT NULL,
  `address_id` BIGINT(20) NOT NULL,
  `city` VARCHAR(32) DEFAULT NULL,
  `status` TINYINT(4) DEFAULT NULL,
  `creator` VARCHAR(32) DEFAULT NULL,
  `create_time` DATETIME DEFAULT NULL,
  `updater` VARCHAR(32) DEFAULT NULL,
  `update_time` DATETIME DEFAULT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;



CREATE TABLE `tb_dict` (
  `id` BIGINT UNSIGNED NOT NULL COMMENT '主键',
  `status_code` TINYINT NOT NULL DEFAULT 1 COMMENT '状态编号',
  `status_name` VARCHAR(10) NOT NULL DEFAULT '' COMMENT '状态名称',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_status_code` (`status_code`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='状态码表';

CREATE TABLE `tb_student` (
  `order_id` BIGINT(20) NOT NULL COMMENT '主键',
  `user_id` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '用户id',
  `price` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '价格(单位:分)',
  `order_status` TINYINT UNSIGNED NOT NULL DEFAULT '1' COMMENT '订单状态(1:待付款,2:已付款,3:已取消)',
  `order_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `title` VARCHAR(100)  NOT NULL DEFAULT '' COMMENT '订单标题',
  PRIMARY KEY (`order_id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_order_time` (`order_time`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

CREATE TABLE `tb_student_1` (
  `order_id` BIGINT(20) NOT NULL COMMENT '主键',
  `user_id` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '用户id',
  `price` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '价格(单位:分)',
  `order_status` TINYINT UNSIGNED NOT NULL DEFAULT '1' COMMENT '订单状态(1:待付款,2:已付款,3:已取消)',
  `order_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `title` VARCHAR(100)  NOT NULL DEFAULT '' COMMENT '订单标题',
  PRIMARY KEY (`order_id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_order_time` (`order_time`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';


CREATE TABLE `tb_student_2` (
  `order_id` BIGINT(20) NOT NULL COMMENT '主键',
  `user_id` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '用户id',
  `price` INT UNSIGNED NOT NULL DEFAULT '0' COMMENT '价格(单位:分)',
  `order_status` TINYINT UNSIGNED NOT NULL DEFAULT '1' COMMENT '订单状态(1:待付款,2:已付款,3:已取消)',
  `order_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `title` VARCHAR(100)  NOT NULL DEFAULT '' COMMENT '订单标题',
  PRIMARY KEY (`order_id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_order_time` (`order_time`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

4 application配置(需要哪个放开注释就可以)

server:
  port: 7010
spring:
  profiles:
    active: sharding
  application:
    name: jeecg-sharding
  config:
    import:
      - optional:nacos:jeecg.yaml
      - optional:nacos:jeecg-@profile.name@.yaml
      #导入classpath下,按照年月范围分表
      #- classpath:sharding-y-m-range-dev.yml
      #导入classpath下,按照年范围分表
      # - classpath:sharding-y-range-dev.yml
      #导入classpath下,分库分表
      #- classpath:application-sharding-multi.yml
      #需求:业务上存在多个分支机构,需要将不同分支的客户拆分到不同的表
      #- classpath:sharding-diff-branch-dev.yml
      #复合分片算法单表
      #- classpath:sharding-complex-dev.yml
      #广播表
      -  classpath:application-sharding-broadcast.yml
  cloud:
    nacos:
      config:
        server-addr: @config.server-addr@
      discovery:
        server-addr: ${spring.cloud.nacos.config.server-addr}

案列

  案列1:按照年月范围分表

 sharding-y-m-range-dev.yml

#单库分表配置
spring:
  shardingsphere:
    props:
      sql-show: true
    datasource:
      names: ds
      #添加分库数据源
      ds:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://jeecg-boot-mysql:3306/shardingjdbc?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
        username: root
        password: xgm@2023..
        type: com.alibaba.druid.pool.DruidDataSource

    # 规则配置
    rules:
      sharding:
        tables:
          # 逻辑表名称
          t_order:
            #配置具体表的数据节点
            actual-data-nodes: ds.t_order_$->{2023..2023}_$->{3..6}
            # 分表策略None(不分片),Inline(最基础的策略、只支持普通的查询和排序),
            #Standard(可支持范围查询,但查询条件若不是分片键或没有查询条件,则查所有表。需要定制具体的分片算法类),
            #Complex(支持范围查询,并支持多分片键的复杂分片策略)
            #Hint(操作时可以指定具体的库、表。无需分片键,只需定制具体的分片算法类)
            table-strategy:
              #分配策略:
              standard:
                # 分片算法名称
                sharding-algorithm-name: table-classbased
                # 分片列名称(对应数据库字段)
                sharding-column: create_time
          t_order_item:
              actual-data-nodes: ds.t_order_item_$->{2023..2023}_$->{3..6}
              table-strategy:
                standard:
                  sharding-column: order_create_time
                  sharding-algorithm-name: table-classbased
        # 配置绑定表,每一行为一组
        binding-tables:
          - t_order,t_order_item
        defaultDataSourceName: ds
        sharding-algorithms:
          table-classbased:
            props:
              strategy: standard
              algorithmClassName: org.jeecg.modules.sharding.algorithm.StandardYMRangeShardAlgorithm
            type: CLASS_BASED
        # 分布式序列算法配置
        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 123


package org.jeecg.modules.sharding.algorithm;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
import org.jeecg.modules.sharding.utils.ShardingUtils;

import java.util.*;


/**
 * @version 1.0
 * @Author zhaozhiqiang
 * @Date 2023/6/16 14:09
 * @Description //TODO 标准年月分表算法
 */
@Slf4j
public class StandardYMRangeShardAlgorithm implements StandardShardingAlgorithm<Date> {
    private Properties props = new Properties();

    public static void main(String[] args) {

        for (int i=0;i<2;i++) {
            //根据值进行取模,得到一个目标值
           int temp= i% 2;
           System.out.println(temp);

        }
        String name="test_01";
        System.out.println(name.indexOf("1"));
    }

    /**
     * 用于处理=和IN的分片
     *
     * @param availableTargetNames           目标/物理表分片的集合(表名)
     * @param preciseShardingValue 逻辑表相关信息  precise准确的
     * @return
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> preciseShardingValue) {
        log.info("精确集合:{},值:{}", JSON.toJSONString(availableTargetNames),JSON.toJSONString(preciseShardingValue));
        Date date = preciseShardingValue.getValue();
        String suffix = ShardingUtils.getSuffixByYearMonth(date);
        for (String tableName : availableTargetNames) {
            if (tableName.endsWith(suffix)) {
                return tableName;
            }
        }
        throw new IllegalArgumentException("未找到匹配的数据表");
    }

    /**
     * 用于处理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理
     *
     * @param availableTargetNames
     * @param rangeShardingValue
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> rangeShardingValue) {
        List<String> list = new ArrayList<>();
        log.info("范围集合:{},值:{}", JSON.toJSONString(availableTargetNames),JSON.toJSONString(rangeShardingValue));
        Range<Date> valueRange = rangeShardingValue.getValueRange();
        Date lowerDate = valueRange.lowerEndpoint();
        Date upperDate = valueRange.upperEndpoint();
        String lowerSuffix = ShardingUtils.getSuffixByYearMonth(lowerDate);
        String upperSuffix = ShardingUtils.getSuffixByYearMonth(upperDate);
        //年月前缀计算
        TreeSet<String> suffixList = ShardingUtils.getSuffixYMListForRange(lowerSuffix, upperSuffix);
        for (String tableName : availableTargetNames) {
            if (containTableName(suffixList, tableName)) {
                list.add(tableName);
            }
        }
        log.info("match tableNames-----------------------" + list.toString());
        return list;
    }
    private boolean containTableName(Set<String> suffixList, String tableName) {
        boolean flag = false;
        for (String s : suffixList) {
            if (tableName.endsWith(s)) {
                flag = true;
                break;
            }
        }
        return flag;
    }
    /**
     * 初始化对象的时候调用的方法
     */
    @Override
    public void init() {
    }

    /**
     * 对应分片算法(sharding-algorithms)的类型
     *
     * @return
     */
    @Override
    public String getType() {
        return "STANDARD_MOD";
    }

    @Override
    public Properties getProps() {
        return this.props;
    }

    /**
     * 获取分片相关属性
     *
     * @param properties
     */
    @Override
    public void setProps(Properties properties) {
        this.props = properties;
    }
}
package org.jeecg.modules.sharding.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.sharding.entity.Order;
import org.jeecg.modules.sharding.service.IOrderItemService;
import org.jeecg.modules.sharding.service.IOrderService;
import org.jeecg.modules.sharding.utils.DateUtils;
import org.jeecg.modules.sharding.vo.OrderAndItemVo;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

@Api(tags = "按照年范围分表")
@RestController
@RequestMapping("/sharding/y")
@Slf4j
public class ShardingYRangeController {
    @Resource
    private IOrderService orderService;

    @Resource
    private IOrderItemService orderItemService;
    /**
     * 制造测试数据
     *
     * @return
     */
    @ApiOperation(value = "制造测试数据", httpMethod = "POST")
    @PostMapping("/initData")
    public Result<?> initData() {
        orderService.initData();
        return Result.OK();
    }
    @ApiOperation(value = "根据时间段查询列表数据", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "bgtm", value = "开始时间", required = false, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "edtm", value = "结束时间", required = false, dataType = "String", paramType = "query")
    })
    @GetMapping("/listAllByDate")
    public Result<?> listAll(@RequestParam(value = "bgtm", required = false) String bgtm, @RequestParam(value = "edtm", required = false) String edtm) {
        LambdaQueryWrapper<Order> objectLambdaQueryWrapper = new LambdaQueryWrapper<Order>();
        if(StringUtils.isNotBlank(bgtm)&&StringUtils.isNotBlank(edtm)){
            objectLambdaQueryWrapper.between(Order::getCreateTime, DateUtils.parseDate(bgtm), DateUtils.getEndTimeOfDay(edtm));
            objectLambdaQueryWrapper.orderByDesc(Order::getCreateTime);
        }
        List<Order> list = orderService.list(objectLambdaQueryWrapper);
        return Result.OK(list);
    }
}
package org.jeecg.modules.sharding.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.sharding.entity.Order;
import org.jeecg.modules.sharding.vo.OrderAndItemVo;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author XHD
 * @since 2020-07-16
 */
public interface OrderMapper extends BaseMapper<Order> {

    List<Order> listByRowNum(@Param("suffix") String suffix, @Param("size") Integer size, @Param("rowNum") Integer rowNum
            , @Param("userName") String userName);

    List<OrderAndItemVo> getItemByParentId(@Param("id")Long id, @Param("name")String name, @Param("createTime")String createTime);

    List<Order> getUnBindLis(@Param("id")Long id,@Param("createTime")String createTime);

    List<Order> unitMainAndShardingList(@Param("id")Long id,@Param("createTime")String createTime);
}

<?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="org.jeecg.modules.sharding.mapper.OrderMapper">
     <select id="listByRowNum" resultType="org.jeecg.modules.sharding.entity.Order">
        SELECT
            A.*
        FROM
            (
            SELECT
                @rownum := @rownum + 1 AS rowNum,
                t.id,t.name,t.create_time,t.user_name
            FROM
                t_order_${suffix} t,
                ( SELECT @rownum := 0 ) r
            <trim prefix="WHERE" prefixOverrides="AND|OR">
                <if test="userName != null and userName != ''">
                   AND t.user_name = #{userName}
                </if>
            </trim>
            ORDER BY
                create_time DESC,id
            ) A
        WHERE
            A.rowNum > #{rowNum}
            LIMIT #{size}
    </select>

    <select id="getItemByParentId" resultType="org.jeecg.modules.sharding.vo.OrderAndItemVo">
        SELECT
            t1.id AS orderId,
                t1.NAME AS orderName,
                t1.user_name AS userName,
            t2.name AS itemName
        FROM
            t_order t1
                INNER JOIN t_order_item t2
                           ON t1.id = t2.order_id
        where
            1=1
        <if test="id !=null and id!=''">
           and t1.id=#{id}
        </if>

        <if test="createTime !=null and createTime!=''">
            and DATE_FORMAT(t1.create_time, '%Y-%m-%d')=#{createTime}
        </if>
        <if test="name !=null and name !=''">
            and t1.name like CONCAT('%',#{name},'%')
        </if>
    </select>

    <select id="getUnBindLis" resultType="org.jeecg.modules.sharding.entity.Order">
        SELECT
          t1.*
        FROM
          t_order t1
          INNER JOIN t_order_middle_test t2
            ON t1.id = t2.order_id
        WHERE 1 = 1
        <if test="id !=null and id !=''">
            and t2.id=#{id}
        </if>
        <if test="createTime !=null and createTime!=''">
            and DATE_FORMAT(t1.create_time, '%Y-%m-%d')=#{createTime}
        </if>
    </select>

    <select id="unitMainAndShardingList" resultType="org.jeecg.modules.sharding.entity.Order">
        SELECT
        t1.*
        FROM
        t_order t1
        INNER JOIN t_order_middle_main_test t2
        ON t1.id = t2.order_id
        WHERE 1 = 1
        <if test="id !=null and id !=''">
            and t2.id=#{id}
        </if>
        <if test="createTime !=null and createTime!=''">
            and DATE_FORMAT(t1.create_time, '%Y-%m-%d')=#{createTime}
        </if>
    </select>
</mapper>
package org.jeecg.modules.sharding.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.sharding.entity.Order;
import org.jeecg.modules.sharding.entity.OrderItem;
import org.jeecg.modules.sharding.mapper.OrderMapper;
import org.jeecg.modules.sharding.service.IOrderItemService;
import org.jeecg.modules.sharding.service.IOrderService;
import org.jeecg.modules.sharding.utils.DataUtils;
import org.jeecg.modules.sharding.utils.DateUtils;
import org.jeecg.modules.sharding.utils.ShardingUtils;
import org.jeecg.modules.sharding.vo.OrderAndItemVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author XHD
 * @since 2020-07-16
 */
@Service
@DS("sharding")
public class OrderServicImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    @Resource
    private IOrderItemService orderItemService;

    @Override
    public void initData() {
        //主表50万 从表50*2=100万
        int count = 5000;
        //每次入库20条
        int size = 1000;
        List<Order> tempList = new ArrayList<>();
        List<OrderItem> orderItemList = new ArrayList<>();
        while (count > 0) {
            addBatch(count, size, tempList, orderItemList);
            count -= size;
            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public Page<Order> listPage(String bgtm, String edtm, Integer current, Integer size, String userName) {
        Page<Order> pageParam = new Page<>();
        pageParam.setCurrent(current);
        if (null != size) {
            pageParam.setSize(size);
        }
        LambdaQueryWrapper<Order> ew = new LambdaQueryWrapper<>();
        ew.between(Order::getCreateTime, DateUtils.parseDate(bgtm), DateUtils.getEndTimeOfDay(edtm));
        ew.orderByDesc(Order::getCreateTime);
        if (StringUtils.isNotBlank(userName)) {
            ew.eq(Order::getUserName, userName);
        }
        Page<Order> page =this.page(pageParam,ew);
        LambdaQueryWrapper<OrderItem> orderItemWrapper = new LambdaQueryWrapper<OrderItem>()
                .between(OrderItem::getOrderCreateTime, DateUtils.parseDate(bgtm), DateUtils.getEndTimeOfDay(edtm));
        this.appendOrderItem(page.getRecords(), orderItemWrapper);
        return page;
    }

    @Override
    public List<Order> listPageByTime(String lastCreateTime, Integer lastRowNum, Integer size, String userName) {
        //lastCreateTime 有助于快速定位当前查询的分表 ,如果是第一页则可不传,默认使用当前时间
        Date date = StringUtils.isBlank(lastCreateTime) ? new Date() : DateUtils.parseTime(lastCreateTime);
        String suffix = ShardingUtils.getSuffixByYearMonth(date);
        int resultSize = size == null ? 10 : size;
        //rowNum用于获取当前页数据的起始位置,如果是第一页可以不传,默认为0
        int rowNum = lastRowNum == null ? 0 : lastRowNum;
        List<Order> orderList = baseMapper.listByRowNum(suffix, resultSize, rowNum, userName);
        if (orderList.size() > 0) {
            while (orderList.size() < resultSize) { //查询出的数据不足 找更早的分表补足
                if ("2020_6".equals(suffix)) {    //假设最早的分表为 t_order_2020_6
                    break;
                }
                suffix = ShardingUtils.getPrevSuffix(suffix);
                List<Order> tempOrderList = baseMapper.listByRowNum(suffix, resultSize - orderList.size(), 0, userName);
                if (tempOrderList.size() > 0) {
                    orderList.addAll(tempOrderList);
                }
            }
            //获取orderList中数据的时间范围 查询子表数据
            LambdaQueryWrapper<OrderItem> orderItemWrapper = new LambdaQueryWrapper<OrderItem>()
                    .between(OrderItem::getOrderCreateTime, orderList.get(orderList.size() - 1).getCreateTime(), orderList.get(0).getCreateTime());
            this.appendOrderItem(orderList, orderItemWrapper);
        }
        return orderList;
    }

    @Override
    public Order findById(Long id, String createTime) {
        LambdaQueryWrapper<Order> ew = new LambdaQueryWrapper<>();
        ew.eq(Order::getCreateTime,DateUtils.parseTime(createTime));
        ew.eq(Order::getId,id);
        Order one = this.getOne(ew);
        return one;
    }

    @Override
    public void removeById(Long id, String createTime) {
        Order entity=new Order();
        entity.setId(id);
        entity.setCreateTime(DateUtils.parseTime(createTime));
        this.removeById(entity);
    }

    @Override
    public  List<OrderAndItemVo> getItemByParentId(Long id, String name, String createTime) {
       return baseMapper.getItemByParentId(id,name,createTime);
    }

    @Override
    public List<Order> getUnBindLis(Long id,String createTime) {
        return baseMapper.getUnBindLis(id,createTime);
    }

    @Override
    public List<Order> unitMainAndShardingList(Long id, String createTime) {
        return baseMapper.unitMainAndShardingList(id,createTime);
    }

    private void appendOrderItem(List<Order> orderList, LambdaQueryWrapper<OrderItem> ew) {
        if (null != orderList && orderList.size() > 0) {
            Set<Long> orderIds = orderList.stream().map(Order::getId).collect(Collectors.toSet());
            ew.in(OrderItem::getOrderId, orderIds).orderByDesc(OrderItem::getOrderCreateTime);
            List<OrderItem> orderItemList = orderItemService.list(ew);
            Map<Long, List<OrderItem>> orderItemMap = DataUtils.listToMapForLong("orderId", orderItemList);
            orderList.forEach(order -> order.setOrderItemList(orderItemMap.get(order.getId())));
        }
    }

    private void addBatch(int ct, int size, List<Order> tempList, List<OrderItem> orderItemList) {
        for (int i = 0; i < size; i++) {
            long orderId = IdWorker.getId();
//            Date orderCreateTime = randomCreateTime(new Random());
            Date orderCreateTime = new Date();
            tempList.add(new Order().setId(orderId).setName("订单-" + (ct - i)).setCreateTime(orderCreateTime)
                    .setUserName("guest-" + new Random().nextInt(1000)));
            orderItemList.add(new OrderItem().setOrderId(orderId).setName("商品-" + (ct * 2 - i * 2)).setOrderCreateTime(orderCreateTime));
            orderItemList.add(new OrderItem().setOrderId(orderId).setName("商品-" + (ct * 2 - i * 2 - 1)).setOrderCreateTime(orderCreateTime));
        }
        saveBatch(tempList);
        orderItemService.saveBatch(orderItemList);
        tempList.clear();
        orderItemList.clear();
    }

//    private Date randomCreateTime(Random random) {
//        Calendar calendar = Calendar.getInstance();
//        calendar.set(Calendar.YEAR, 2023);
//        calendar.set(Calendar.MONTH, 5);
//        calendar.set(Calendar.DAY_OF_MONTH, random.nextInt(31) + 1);
//        calendar.set(Calendar.HOUR_OF_DAY, random.nextInt(24));
//        calendar.set(Calendar.MINUTE, random.nextInt(60));
//        calendar.set(Calendar.SECOND, random.nextInt(60));
//        return calendar.getTime();
//    }

}

后续代码太多就不一一贴出来,下载地址

https://download.csdn.net/download/weixin_38501485/87917171

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/653584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hector SLAM Scan Matching 理解

Hector SLAM 参考https://www.cnblogs.com/cyberniklee/p/8484104.html 搞清楚几个点有助于对scan matching的理解 占用栅格地图中每个地图点包括点坐标、占用值最大为1&#xff0c;表示该栅格被占用的概率、以及占用值对坐标的梯度&#xff0c;由于地图点是离散的&#xff…

HashMap底层实现

首先来看一下put方法的源码&#xff0c;在HashMap中最重要的就是put方法的执行逻辑以及一些控制参数的意义比较重要。 【put方法】 问题1&#xff1a;如何计算数组位置&#xff1f; 答案&#xff1a; 1、首先在插入<K &#xff0c;V> 时&#xff0c;会先将其包装成一…

商城系统是如何分账的?-加速度shopfa

微信小程序凭借着其方便快捷&#xff0c;无需下载且依附于微信这个庞大的社交平台等特点&#xff0c;让无数的企业商家都为之痴迷&#xff0c;并都纷纷投入到了小程序的搭建工作&#xff0c;但你知道吗&#xff0c;通过小程序进行交易&#xff0c;资金的结算是十分复杂的&#…

使用单元测试框架unittest进行有效测试

一、介绍 在软件开发中&#xff0c;单元测试是一种测试方法&#xff0c;它用于检查单个软件组件&#xff08;例如函数或方法&#xff09;的正确性。Python 提供了一个内置的单元测试库&#xff0c;名为 unittest&#xff0c;可以用来编写测试代码&#xff0c;然后运行测试&…

基于Java图书管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

springboot+vue漫画网站(java项目源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的漫画网站。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌&#…

Elasticsearch:实用 BM25 - 第 2 部分:BM25 算法及其变量

BM25算法 我将尽可能深入这里的数学以解释正在发生的事情&#xff0c;但这是我们查看 BM25 公式的结构以深入了解正在发生的事情的部分。 首先我们来看看公式&#xff0c;然后我将把每个组件分解成可以理解的部分&#xff1a; 我们可以看到一些常见的组件&#xff0c;如 qi、I…

第二期丨INTERSPEECH 2023 论文预讲会

INTERSPEECH 2023 论文预讲会是由CCF语音对话与听觉专委会、语音之家主办&#xff0c;旨在为学者们提供更多的交流机会&#xff0c;更方便、快捷地了解领域前沿。活动将邀请 INTERSPEECH 2023 录用论文的作者进行报告交流。 INTERSPEECH 2023 论文预讲会第二期邀请到华南理工大…

无线耳机什么牌子的好?质量好性价比高 ?八款蓝牙耳机分享

随着TWS技术在应用层面的日益完善&#xff0c;真无线蓝牙耳机就越来越受欢迎了&#xff0c;完全摒弃了线材的束缚&#xff0c;做到了真正的无线耳机&#xff0c;这简直是无法忍受耳机线的强迫症的福音&#xff0c;而且现在不仅是佩戴时会格外的舒适&#xff0c;随着无线技术的不…

【面试题必问】浏览器是如何实现生成HTTP消息的

我们经常会使用浏览器访问各种网站&#xff0c;获取各种信息&#xff0c;帮助解决工作生活中的问题。那你知道&#xff0c;浏览器是怎么帮助我们实现对web服务器的访问&#xff0c;并返回给我们想要的信息吗&#xff1f; 1. 浏览器生成HTTP消息 我们平时使用的浏览器有很多种&…

图解LeetCode——437. 路径总和 III

一、题目 给定一个二叉树的根节点 root &#xff0c;和一个整数 targetSum &#xff0c;求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始&#xff0c;也不需要在叶子节点结束&#xff0c;但是路径方向必须是向下的&#xff08;只能从父节点到…

AI智能视频技术在安防监控领域的场景应用

AI智能视频技术是一种基于人工智能、深度学习和计算机视觉等技术的视频处理技术。它可以通过对视频进行分析和识别&#xff0c;实现各种智能化应用&#xff0c;如视频监控、智能家居、自动驾驶等。 目前&#xff0c;AI智能视频技术已经实现了人脸识别、行为分析、智能跟踪、场…

测试用例excel转word(Office word篇)

场景 我们在项目中&#xff0c;默认情况下是用我们的Excel用例模版输出测试用例。但是有的项目中&#xff0c;会要求在Word版本的测试计划或者测试报告中&#xff0c;写明测试用例。而我们的测试用例&#xff0c;有的项目有上千条&#xff0c;这个时候如果从Excel往Word中复制…

【支付宝小程序】医保接入文档网址

【支付宝小程序】医保接入文档 自己注意事项&#xff1a; 授权 my.getAuthCode跳转与参数 处理 my.ap.navigateToAlipayPage联调 测试开发者加入 白名单

【前端播放器】修改前端参数,减少时延

目录 程序修改 海康 CM8 换上新的jessibuca-3 好像提高到了1S内 与2.8的旧版本比下 191-196-2.8三个对比 jessibuca-pro 延时测试 jessibuca-pro 300ms 超低延迟 wvp-webrtc wvp-webrtc vs vms webrtc > jessibuca-pro > jessibuca 总体 参考资料 程序修改 …

不要把异常当做业务逻辑,这性能可能你无法承受

一&#xff1a;背景 1. 讲故事 在项目中摸爬滚打几年&#xff0c;应该或多或少的见过有人把异常当做业务逻辑处理的情况(┬&#xff3f;┬)&#xff0c;比如说判断一个数字是否为整数,就想当然的用try catch包起来&#xff0c;再进行 int.Parse&#xff0c;如果抛异常就说明不…

基于Java家居商城系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

pl/sql developer oracle生僻字显示问题

一、问题由来 随着国标GB18030的推行&#xff0c;各行各业都在如火如荼的落实改造。自己在工作中也发现很多问题&#xff0c;查阅了很多资料都未解决自己的问题。经过慢慢摸索&#xff0c;对生僻字经常出现的问题进行总结&#xff0c;现分享如下。 二、问题描述 1. or…

超声功率放大器的工作原理和特点是什么

超声功率放大器是一种利用超声波振动产生机械振动的装置&#xff0c;通过将输入信号放大后输出到负载中&#xff0c;以实现对超声能量的有效利用。其工作原理和特点如下&#xff1a; 超声功率放大器的工作原理 超声功率放大器的工作原理是基于压电效应和磁致伸缩效应。当输入电…

2023亚马逊科技中国峰会之Amazon DeepRacer赛车比赛

目录 一、前言 二、什么是 Amazon DeepRacer 三、如何构建自己的第一个强化学习模型 1、创建 Amazon DeepRacer 资源 2、自定义你的赛道 3、开始你的模型 4、关于优化模型 5、在仿真器中测试 6、在真实赛道上测试你的模型 四、中国峰会总决赛 五、自动驾驶赛车名校邀…