springboot 按月分表的实现方式

下面是springboot按月分表的实现方式完整攻略:

第一步:创建表和初始化数据

首先,我们需要创建一张原始的订单表,结构如下:

CREATE TABLE `order` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `order_no` varchar(64) DEFAULT NULL COMMENT '订单号',
  `order_amount` decimal(10,2) DEFAULT NULL COMMENT '订单金额',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

接下来,初始化一些数据,可以通过以下SQL语句插入数据:

INSERT INTO `order`(order_no, order_amount, create_time) VALUES 
('202201010001', 100, '2022-01-01 10:10:10'), 
('202201020001', 300, '2022-01-02 10:10:10'),
('202202010001', 200, '2022-02-01 10:10:10');

第二步:实现按月分表的方式

定义分表规则

首先,我们需要定义分表规则,这里我们选择按照订单创建时间来进行分表,即每个月一张表。

创建分表的SQL语句

接下来,我们可以通过以下SQL语句来创建按月分表的订单表:

CREATE TABLE IF NOT EXISTS `order_{0}` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `order_no` varchar(64) DEFAULT NULL COMMENT '订单号',
  `order_amount` decimal(10,2) DEFAULT NULL COMMENT '订单金额',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

上面的语句中,{0}表示动态的表名后缀,例如表名为order_202201

实现分表的代码逻辑

最后,我们可以通过实现springboot的拦截器和多数据源来实现按月分表的逻辑。

首先,我们要实现拦截器,来根据订单创建的时间来判断应该使用哪个数据源,代码示例:

@Component
public class OrderTableInterceptor implements HandlerInterceptor {

    private static final String TABLE_PREFIX = "order_";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String orderNo = request.getParameter("orderNo");
        if (StringUtils.isEmpty(orderNo)) {
            throw new BusinessException("orderNo不能为空");
        }
        Date createTime = getOrderCreateTime(orderNo);
        if (createTime == null) {
            throw new BusinessException("获取订单创建时间失败");
        }

        String dataSourceKey = TABLE_PREFIX + DateUtil.format(createTime, "yyyyMM");
        DataSourceContextHolder.setDataSourceKey(dataSourceKey);
        return true;
    }

    /**
     * 根据订单号获取订单创建时间
     */
    private Date getOrderCreateTime(String orderNo) {
        // 查询订单,返回订单创建时间
        // 这里假设根据订单号从数据库中查询出来的订单创建时间为:2022-01-01 10:10:10
        return DateUtil.parse("2022-01-01 10:10:10");
    }
}

在上面的代码中,我们首先根据订单号获取订单创建时间,然后将订单创建时间格式化成表名的后缀,例如订单创建时间为2022-01-01 10:10:10,则表名后缀为202201。最后,使用DataSourceContextHolder来动态切换数据源。

接下来,我们还需要实现多数据源的配置和切换,这里我们采用springboot官方推荐的AbstractRoutingDataSource来实现,代码示例:

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceKey();
    }
}

其中,DataSourceContextHolder就是用来保存当前线程要使用的数据源的key。

最后,我们需要在springboot的配置文件中加入以下配置,来指定使用DynamicDataSource作为数据源:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/order?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    initial-size: 3
    min-idle: 3
    max-active: 500
    max-wait: 60000
    time-between-eviction-runs-millis: 60000
    min-evictable-idle-time-millis: 300000
    validation-query: SELECT 1 FROM DUAL
    test-while-idle: true
    test-on-borrow: false
    test-on-return: false

datasource:
  # 按月分表的数据源配置
  order_202201:
    url: jdbc:mysql://localhost:3306/order_202201?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  order_202202:
    url: jdbc:mysql://localhost:3306/order_202202?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

在上面的配置中,我们针对每个月的订单表都配置了一个单独的数据源。

第三步:测试

最后,我们可以通过以下代码来测试按月分表的实现方式:

@RestController
public class OrderController {

    @Autowired
    OrderMapper orderMapper;

    @GetMapping("/order")
    public List<Order> getOrderList(@RequestParam String orderNo) {
        return orderMapper.getOrderList(orderNo);
    }

    @PostMapping("/order")
    public Order addOrder(@RequestBody Order order) {
        orderMapper.addOrder(order);
        return order;
    }
}

其中,OrderMapper是用来操作数据库的Mapper,在里面会使用我们刚刚实现的动态数据源的逻辑。在测试时,可以通过Postman等工具来发送请求,例如:

  • GET http://localhost:8080/order?orderNo=202201010001
  • POST http://localhost:8080/order

测试成功后,就可以使用按月分表的方式来快速的拆分大量的订单数据了。

示例

下面是两个示例:

示例1

假设当前时间为2022年1月,我们要添加一个订单,订单创建时间为2022年1月3日,订单号为202201030001。发送POST请求如下:

POST http://localhost:8080/order
Content-Type: application/json

{
    "orderNo": "202201030001",
    "orderAmount": 200,
    "createTime": "2022-01-03 00:00:00"
}

返回结果如下:

{
    "id": 4,
    "orderNo": "202201030001",
    "orderAmount": 200.00,
    "createTime": "2022-01-03T00:00:00.000+00:00"
}

在数据库中,会自动创建一张名为order_202201的订单表,并且将该订单插入到该表中。

示例2

假设现在要查询订单号为202201010001的订单,发送GET请求如下:

GET http://localhost:8080/order?orderNo=202201010001

返回结果如下:

[
    {
        "id": 1,
        "orderNo": "202201010001",
        "orderAmount": 100.00,
        "createTime": "2022-01-01T10:10:10.000+00:00"
    }
]

在查询时,程序会根据订单创建时间来确定使用哪张表,例如该订单创建时间为2022年1月1日,所以会查询order_202201表,并返回查询结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot 按月分表的实现方式 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • SpringMVC接收前台传递过来的值的实例

    下面我来详细讲解“SpringMVC接收前台传递过来的值的实例”的完整攻略。 1. 前置条件 在开始之前,需要保证你已经: 安装了Java开发环境(JDK) 安装了Spring框架 2. 实例1:接收表单数据 假设我们有一个表单页面,其中包含一个输入框和一个提交按钮,我们需要在后台接收前台传递过来的输入框的值。以下是实现过程: 在表单页面中,添加一个输入框和…

    Java 2023年6月15日
    00
  • struts2入门Demo示例

    下面为你详细讲解“struts2入门Demo示例”的完整攻略: 环境搭建 首先,需要搭建Java环境和Tomcat服务器环境,并下载Struts2框架。这里以Windows环境下为例,具体步骤如下: 安装Java环境 下载JDK并进行安装,自定义安装目录。 配置环境变量JAVA_HOME,值为JDK安装目录路径,例如 C:\Program Files\Jav…

    Java 2023年5月20日
    00
  • Java分布式事务管理框架之Seata

    Java分布式事务管理框架之 Seata 什么是 Seata Seata 是一款开源的分布式事务管理框架,由阿里开源团队于 2019 年推出,提供了针对面向微服务架构的分布式事务解决方案,支持本地事务和全局分布式事务,并且支持多种数据源和多语言、多开发框架。 Seata 支持的事务模式 Seata 支持 AT、TCC、SAGA、XA 四种事务模式,其中: A…

    Java 2023年5月20日
    00
  • JavaScript中的数组特性介绍

    关于JavaScript中的数组特性,我们可以从以下几个方面进行介绍: 数组的创建和初始化 JavaScript中的数组可以使用字面量和构造函数两种方式进行创建和初始化。其中,字面量方式如下: const array = [‘a’, ‘b’, ‘c’]; 构造函数方式如下: const array = new Array(‘a’, ‘b’, ‘c’); 需要…

    Java 2023年5月26日
    00
  • 详解MyBatis Generator自动创建代码(dao,mapping,poji)

    下面我将详细讲解MyBatis Generator自动创建代码的完整攻略,包括使用步骤和示例说明。 MyBatis Generator是什么 MyBatis Generator是MyBatis框架家族中的一员,是一款自动生成MyBatis持久层代码(Mapper接口和Mapper XML文件)的工具。它是根据数据库表结构自动生成对应的JavaBean、Map…

    Java 2023年6月1日
    00
  • 什么是双亲委派模型?

    以下是关于双亲委派模型的详细讲解: 什么是双亲委派模型? 双亲委派模型是一种类加载机制,它是由 Java 虚拟机(JVM)实现的。在双亲委派模型中,当一个类加载器收到类加载请求时,它首先将请求委派给父类加载器,如果父类加载器无法加载该类,则将请求委派给其子类加载器。这个过程会一直持续到顶层的启动类加载器,如果启动类加载器无法加载该类,则会抛出 ClassNo…

    Java 2023年5月12日
    00
  • ASP开发中存储过程应用全接触

    ASP开发中存储过程应用全接触 什么是存储过程? 在数据库中,存储过程是一组为了完成特定任务的SQL语句集合。存储过程可以接收数据、处理数据并返回数据,它可以调用其他存储过程、控制逻辑、计划任务和其他编程构造。存储过程可以显著提高数据库的性能,同时也具备一些安全性和封装性方面的优势。在ASP开发中使用存储过程,可以使代码结构更清晰,可维护性更高,同时也能提高…

    Java 2023年6月16日
    00
  • Java fastdfs客户端实现上传下载文件

    Java FastDFS客户端实现上传下载文件 本文将详细介绍如何使用Java FastDFS客户端来实现文件的上传和下载。 什么是FastDFS FastDFS是一个开源的高性能分布式文件系统,它对文件进行管理、存储和访问,使得文件的存储、上传、下载、删除变得简单和高效。FastDFS采用分布式架构,可以进行横向扩容和负载均衡,支持海量数据存储。它适合于文…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部