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日

相关文章

  • 使用Spring的拦截器监测每个Controller或方法的执行时长

    使用Spring的拦截器监测每个Controller或方法的执行时长 在Spring中,我们可以使用拦截器来监测每个Controller或方法的执行时长。拦截器是一种AOP(面向切面编程)技术,它可以在方法执行前、执行后或抛出异常时执行一些操作。本文将详细讲解如何使用Spring的拦截器监测每个Controller或方法的执行时长。 1. 创建拦截器 首先,…

    Java 2023年5月18日
    00
  • Log4j 配置日志打印时区的实现方法

    下面是具体的攻略: 1. 前言 Log4j 是一个非常优秀的 Java 日志组件,其可以方便的对 Java 应用的运行时状态进行记录和追踪。在对日志进行格式化输出时,Log4j 默认使用的是本地的时间,而不是 UTC 时间。这就导致在跨时区的场景下,输出的时间可能会出现时间误差的问题。因此,在 Log4j 中配置时区信息是非常必要的。 2. 实现方法 2.1…

    Java 2023年5月20日
    00
  • IDEA2020.1启动SpringBoot项目出现java程序包:xxx不存在

    当使用IDEA 2020.1版本启动Spring Boot项目时,可能会遇到以下错误提示: java程序包:xxx不存在 这个错误通常是由于项目的依赖项有问题导致的。为了解决这个问题,可以采取以下步骤: 步骤一:清除Maven本地仓库 打开命令行窗口,输入以下命令清除Maven本地仓库: mvn clean 这个命令会清除本地Maven仓库中的缓存文件。接下…

    Java 2023年5月19日
    00
  • Java Object类中的常用API介绍

    下面我将为您详细讲解“Java Object类中的常用API介绍”的攻略。 Object类的作用 在Java中,所有的类都继承自Object类,因此Object类中包含了许多常用的API,这些API可以用于所有的Java类,因此了解Object类的API也是非常重要的。 常用的Object类API介绍 下面我们将介绍几个常用的Object类API。 equa…

    Java 2023年5月26日
    00
  • window.location和document.location的区别分析

    下面我将详细讲解一下“window.location和document.location的区别分析”的攻略。 标题 简介 window.location和document.location是JavaScript中的两个对象,它们都表示当前页面的URL地址。虽然它们的属性和方法非常相似,但它们之间是有一些区别的。 window.location和documen…

    Java 2023年6月15日
    00
  • 常见的 JVM 参数有哪些?

    以下是关于常见的 JVM 参数的完整使用攻略: 常见的 JVM 参数 JVM 参数是用来控制 JVM 行为的一些参数,可以通过命令行或配置文件等方式传递给 JVM。常见的 JVM 参数包括堆相关参数、垃圾回收器相关参数、线程相关参数和其他参数。 堆相关参数 堆是 JVM 中存储对象的内存区域,堆相关参数可以用来控制 JVM 的堆大小和堆的分配方式。 -Xms…

    Java 2023年5月12日
    00
  • 什么是线程安全的集合?

    以下是关于线程安全的集合的完整使用攻略: 什么是线程安全的集合? 线程安全的集合是指多个线程可以同时访问的集合,而不会出现数据不一致或程序崩溃等问题。在多线程编程中,线程安全的集合是非常重要的,因为多个线程同时访问集合时,可能会出现线程间争用的问题,导致数据不一致或程序崩溃。 线程全的集合的示例 以下两个示例,分别演示了线程安全的集合的实现过程。 示例一:线…

    Java 2023年5月12日
    00
  • Java购物系统设计与实现

    Java购物系统设计与实现的攻略 1. 系统需求分析 在进行设计之前,必须要深入了解用户需求。这里假设我们设计的是一个在线商城,需要实现以下功能: 商品列表展示 商品搜索 购物车添加、修改和删除商品 下单支付 订单查询和查看订单详情 2. 数据库设计 根据需求,需要定义以下数据库表: 商品表:包含商品ID,商品名称,商品价格等信息 用户表:包括用户ID,用户…

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