Java - 更新分表数据

前言

在数据量较大时,会选择将一张表分为多张分表保存对应数据,常见以数字为后缀为分表命名。更新插入数据时,需要指定分表写入。

示例
原表:consume_data
分表:consume_data_01、consume_data_02、consume_data_03、consume_data_04、…
每张分表的字段都完全一致。

实体类

public class ConsumeData{

    private Long id;
    
    private String phoneNum;

	private Date createTime;
	
}

一、获取分表后缀

1.根据指定值分组

根据实体类中的手机号作为指定分表的条件

List<ConsumeData> list = new ArrayList<>();

//按手机号的最后两位分组
Map<String, List<ConsumeData>> groupByMap = list.stream()
	.collect(Collectors.groupingBy(x -> x.getPhoneNum()
	.substring(x.getPhoneNum().length() - 2)));

// 遍历获取手机号最后两位以及对应的数据集合
for (Map.Entry<String, List<ConsumeData>> entry : groupByMap.entrySet()) {
   String tableSuffix = entry.getKey();
   List<ConsumeData> suffixList = entry.getValue();
}

2.根据时间分组

根据实体类中的时间作为加入分表的条件

List<ConsumeData> list = new ArrayList<>();

// 按照年月分组 202401
Map<String, List<ConsumeData>> groupByMap = list.stream().filter(x -> x.getCreateTime() != null).collect(Collectors.groupingBy(item -> {
    Date createTime = item.getCreateTime();
    calender.setTime(createTime);

    int year = calender.get(Calendar.YEAR);
    int month = calender.get(Calendar.MONTH) + 1;
    // month <10 前补0
    String yearMonth = year + "" + (month < 10 ? "0" + month : month);   
    return yearMonth;
}));

获取年月季度

Calendar calendar = Calendar.getInstance();
// 获取当前年
int year = calendar.get(Calendar.YEAR);
// 获取当前月
int month = calendar.get(Calendar.MONTH) + 1;
// 当前季度
int quarter = (month%3 == 0)?(month/3):(month/3+1);

二、更新分表数据

1.传入表后缀拼接

mapper类

void insertBatch(@Param("list") List<ConsumeData> list, @Param("tableSuffix") String tableSuffix);

xml

<insert id="insertBatch">
        INSERT INTO consume_data_${tableSuffix}(consume_id,phone_num,create_time)
        values
        <foreach collection="list" item="item" separator=",">
            (#{item.consumeId}, #{item.phoneNum}, #{item.createTime})
        </foreach>
</insert> 

2.mybatis-plus 动态表名

(1)Mybatis-Plus配置

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.ArrayList;
import java.util.List;

/**
 * Mybatis Plus 配置
 *
 * @author ruoyi
 */
@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig
{
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor()
    {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor());
        // 乐观锁插件
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
        // 阻断插件
        interceptor.addInnerInterceptor(blockAttackInnerInterceptor());

		// 动态表名拦截器
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            String newTable = null;
            for (String table : tableList()) {
                newTable = RequestDataHelper.getRequestData(table);
                if (table.equals(tableName) && newTable!=null){
                    tableName = newTable;
                    break;
                }
            }
            return tableName;
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }

	// 设置需要动态设置表名的表
	static List<String> tableList(){
        List<String> tables = new ArrayList<>();
        tables.add("comsume_data");
        return tables;
    }

    /**
     * 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html
     */
    public PaginationInnerInterceptor paginationInnerInterceptor()
    {
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // 设置数据库类型为mysql
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        return paginationInnerInterceptor;
    }

    /**
     * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html
     */
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor()
    {
        return new OptimisticLockerInnerInterceptor();
    }

    /**
     * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html
     */
    public BlockAttackInnerInterceptor blockAttackInnerInterceptor()
    {
        return new BlockAttackInnerInterceptor();
    }
}

(2)请求参数传递辅助类

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();
    }
}

(3)设置表名

public void setTable (String month){
       String table = "consume_data_" + month;
            RequestDataHelper.setRequestData(new HashMap<String, Object>() {{
                put("consume_data", table);
            }});
}

(4)更新数据

public void updateDataById(ConsumeData consumeData, String month) {
	consumeData = new ConsumeData();
	consumeData.setConsumeId(1L);
	consumeData.setPhoneNum(19111111111);
	consumeData.setCreateTime(new Date());
	
	// 动态设置分表
	setTable(month);
	// 更新数据
	this.updateById(consumeData);
}
  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值