MybatisPlus按月分表

思路分为两步

一步是每月底自动创建下月的表,通过存储过程(创建表)和事件(定时调用存储过程)实现

第二步是项目中用mybatisPlus的DynamicTableNameInnerInterceptor拦截器对访问该表的数据库操作进行拦截,重新构建sql语句

创建存储过程示例:

DROP PROCEDURE
IF
	EXISTS create_order_by_month;
CREATE DEFINER=`root`@`localhost` PROCEDURE `create_order_by_month`()
BEGIN
	DECLARE
		nextMonthStr VARCHAR ( 6 );
	DECLARE
		createStr VARCHAR ( 2000 );
	
	SET @nextMonthStr = DATE_FORMAT( DATE_ADD( NOW(), INTERVAL 1 MONTH ), '%Y%m' );
	
	SET @createStr = CONCAT( "CREATE TABLE `sms_order_", @nextMonthStr, "`  (
		`id` int(11) NOT NULL AUTO_INCREMENT,
		`bc_id` int(11) DEFAULT NULL COMMENT '计费代码id,关联bc.id',
		`user_mobile` varchar(11) DEFAULT NULL COMMENT '用户手机号',
		`province` varchar(50) DEFAULT NULL COMMENT '省',
		`order_no` varchar(25) DEFAULT NULL COMMENT '订单号',
		`status` int(11) NOT NULL DEFAULT '0' COMMENT '用户订购状态:0 默认值,1 退订,2 订购,3 支付失败',
		`status_desc` varchar(500) DEFAULT NULL COMMENT '状态描述',
		`valid_code` varchar(10) DEFAULT NULL COMMENT '验证码',
		`price` int(11) DEFAULT NULL COMMENT '价格(分)',
		`imsi` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
		`imei` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
		`phone_model` varchar(50) DEFAULT NULL COMMENT '用户机型',
		`pay_time` datetime DEFAULT NULL COMMENT '订购时间',
		`cancel_time` datetime DEFAULT NULL COMMENT '退订时间',
		`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
		`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
		PRIMARY KEY (`id`),
		UNIQUE KEY `uq_order_no` (`order_no`) USING BTREE
	) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='订单表';" );
	PREPARE stmt 
	FROM
		@createStr;
	EXECUTE stmt;

END

创建事件定时调用建好的存储过程

-- 以$$作为分隔符
DELIMITER $$  
SET GLOBAL event_scheduler = 1;  
-- 事件名
CREATE EVENT event_create_table_every_month
-- 间隔一个月  
ON SCHEDULE EVERY 1 MONTH
-- 第一次执行时间
STARTS date_add( LAST_DAY(CURDATE()), INTERVAL 0 HOUR ) 
ON  COMPLETION  PRESERVE  
ENABLE  
DO  
BEGIN  
-- 要调用的函数或者存储过程
CALL create_order_by_month();
END $$  
-- 将分隔符重置为;
DELIMITER ;

至此数据库就会每个月自动创建下月的表了,这里设置的是每月最后一天零点创建下月的表

然后就是项目中的处理,实现动态查询当月的表

添加需要用到的依赖

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-generator</artifactId>
	<version>3.5.0</version>
</dependency>

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.5.1</version>
</dependency>

然后定义mbp的拦截类,实现根据传入订单号动态查询对应月份的订单表

package cn.com.ilives.smsnew.config;

import cn.com.ilives.smsnew.helper.RequestDataHelper;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;



@Configuration
@MapperScan("cn.com.ilives.smsnew.mapper")
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            if (StringUtils.isNotEmpty(tableName) && "sms_order".equals(tableName)) {
                Map<String, Object> requestData = RequestDataHelper.getRequestData();
                String orderNo = String.valueOf(requestData.get("orderNo"));
                String tIndex = orderNo.substring(0, 6);
                return tableName + "_" + tIndex;
            }else {
                return tableName;
            }
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }
}

还有一个请求参数传递辅助类

package cn.com.ilives.smsnew.helper;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import java.util.Map;

/**
 * 请求参数传递辅助类
 */
public class RequestDataHelper {
    /**
     * 请求参数存取
     */
    private static final ThreadLocal<Map<String, Object>> REQUEST_DATA = new ThreadLocal<>();

    /**
     * 设置请求参数
     *
     * @param requestData 请求参数 MAP 对象
     */
    public static void setRequestData(Map<String, Object> requestData) {
        REQUEST_DATA.set(requestData);
    }

    /**
     * 获取请求参数
     *
     * @param param 请求参数
     * @return 请求参数 MAP 对象
     */
    public static <T> T getRequestData(String param) {
        Map<String, Object> dataMap = getRequestData();
        if (CollectionUtils.isNotEmpty(dataMap)) {
            return (T) dataMap.get(param);
        }
        return null;
    }

    /**
     * 获取请求参数
     *
     * @return 请求参数 MAP 对象
     */
    public static Map<String, Object> getRequestData() {
        return REQUEST_DATA.get();
    }
}

业务层里会访问此表的方法,都用请求参数传递辅助类传递动态构建表名所需的参数。以此达到访问当月表的目的


    @Override
    public Integer saveOrder(Order order) {
//    就是这部分
        RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
            put("orderNo", order.getOrderNo());
        }});
//    ————————————

        return orderMapper.insert(order);
    }

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值