springboot sharding-jdbc分表


文章例子为按月份分表,将表按月份分为(表_1,表_2…表_12)
ShardingSphere

pom文件导包

    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.8.5</version>
    </dependency>
   
    <dependency>
		<groupId>org.apache.shardingsphere</groupId>
		<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
		<version>4.1.1</version>
	</dependency>

yml配置

spring:
  shardingsphere:
    datasource: # 数据源
      master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        username: ## 用户名称
        password: ## 密码
        jdbcUrl: jdbc:mysql://ip:host/数据库名?useUnicode=true&amp;autoReconnect=true&amp;characterEncoding=UTF-8&useSSL=true&zeroDateTimeBehavior=convertToNull
      names: master
    props:
      sql.show: true #是否开启SQL显示,默认值: false
      max.connections.size.per.query: 8 # 每个查询可以打开的最大连接数量,默认为1,此处可加快项目启动时shardingsphere加载数据库表元数据的速度
    sharding:
      tables:
        ${表前缀}: # 如 t_a_1~t_a_12写t_a
          actual-data-nodes: master.表前缀_$->{1..12}  #表分布情况 {数据源分支.表名}
          table-strategy:
            standard: # 数据库表分片策略
              shardingColumn: insert_time ##按该字段分片
              preciseAlgorithmClassName: **.MonthPreciseShardingAlgorithm  ##对应类全路径
              rangeAlgorithmClassName: **.MonthRangeShardingAlgorithm ##对应类全路径

sharding数据库配置

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * 数据库配置
 *
 */
@Configuration
@MapperScan(basePackages = "分表dao类所在包", sqlSessionTemplateRef = "shardingSqlSessionTemplate")
public class ShardingDataSourceConfig {

    @Bean(name = "shardingSqlSessionFactory")
    public SqlSessionFactory shardingSqlSessionFactory(@Qualifier("shardingDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/sharding/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "shardingTransactionManager")
    public DataSourceTransactionManager shardingTransactionManager(@Qualifier("shardingDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "shardingSqlSessionTemplate")
    public SqlSessionTemplate shardingSqlSessionTemplate(@Qualifier("shardingSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}


分片策略

MonthPreciseShardingAlgorithm.java

import cn.hutool.core.date.DateUtil
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

/**
 * 表精确分片算法
 * in或=
 * 按时间月份分片
 * 使用String类型进行分片,则对于分片字段类型应为String
 *
 */
public class MonthPreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
        // 逻辑表名
        String logicTableName = preciseShardingValue.getLogicTableName();
        // 分片值
        String value = preciseShardingValue.getValue();
        if (StringUtils.isBlank(value)) {
            throw new BusinessException("分片值异常");
        }
        int mm = DateUtil.month(DateUtil.parse(value)) + 1;

        return logicTableName + "_" + mm;
    }
}

MonthRangeShardingAlgorithm.java

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

/**
 * 表范围分片
 * <p>
 * 按月份分片
 *
 */
public class MonthRangeShardingAlgorithm implements RangeShardingAlgorithm<String> {
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {

        String logicTableName = rangeShardingValue.getLogicTableName();
        Range<String> valueRange = rangeShardingValue.getValueRange();
        try {
            String startDate = valueRange.lowerEndpoint();
            String endDate = valueRange.upperEndpoint();
            return getMonthTables(startDate, endDate, logicTableName);
        } catch (Exception e) {
            e.printStackTrace();
            return collection;
        }

    }


    /**
     * 获取月表
     *
     * @param startDate      起始时间
     * @param endDate        结束时间
     * @param logicTableName 逻辑表名
     * @return 结果表名列表
     */
    public Set<String> getMonthTables(String startDate, String endDate, String logicTableName) {
        DateTime startDateTime = DateUtil.parse(startDate);
        DateTime endDateTime = DateUtil.parse(endDate);

        Calendar start = Calendar.getInstance();
        Calendar end = Calendar.getInstance();
        start.setTime(startDateTime);
        end.setTime(endDateTime);

        Set<String> result = new HashSet<>();
        // 添加起始月和结束月
        result.add(logicTableName + "_" + (start.get(Calendar.MONTH) + 1));
        result.add(logicTableName + "_" + (end.get(Calendar.MONTH) + 1));

        while (start.before(end)) {
            result.add(logicTableName + "_" + (start.get(Calendar.MONTH) + 1));
            start.add(Calendar.MONTH, 1);
        }

        return result;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值