SpringMVC+myBaties+druid+sharding,按照月份分表

项目需要分表分库,在网上找到了shardingsphere插件,接入过程还是蛮曲折的,今天终于有时间搞通了。sharding的介绍等会再说,还是直接上代码。

一、引入jar包,我使用的v4.0.0版本

             
            
                org.apache.shardingsphere
                sharding-jdbc-core
                ${sharding-sphere.version}
            
            
            
                org.apache.shardingsphere
                sharding-jdbc-spring-namespace
                ${sharding-sphere.version}
            

二、因为是SpringMVC,所以采用基于Spring命名空间的规则配置,具体配置如下:





    

    
    

        
        
        
        
        
        
        

        
        
        
        

        
        

        
        

        
        
        

        
        
        
        
        
        

    

    
    
        
        
            
                classpath*:mapper/*.xml
                classpath*:mapper/**/*.xml
            
        
        
        
            
                
                    
                        helperDialect=mysql
                    
                
            
        
    
    
        
    

    
    
        
    

    
    
    
    
    
        
            
                
            
        
    

我是采用StandardShardingStrategy,标准分片策略提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEEN AND, >, <, >=, <=分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理。

重写了精准分片算法和范围分片算法。具体代码如下:

/**
 * 精准分表算法
 * @author chuhx
 * @date 2020/3/6 11:48
 **/
@Component
public class ShardingTableAlgorithm implements PreciseShardingAlgorithm {
    @Override
    public String doSharding(Collection tableNames, PreciseShardingValue preciseShardingValue) {
        String tableName = "tb_order";
        if(preciseShardingValue.getValue()==null){
            return tableName;
        }
        tableName = Lists.newArrayList(tableNames).get(0);
        String sdValue = DateUtils.format(preciseShardingValue.getValue(),"yyyyMMddHHmmss");
        if(StringUtils.isBlank(sdValue)){
            return tableName;
        }
        return tableName+sdValue.substring(0,6);
    }
}
/**
 * 范围分表算法
 * @author chuhx
 * @date 2020/3/9 17:07
 **/
public class ShardingRangTableAlgorithm implements RangeShardingAlgorithm {
    /**
     * Sharding.
     *
     * @param availableTargetNames available data sources or tables's names
     * @param shardingValue        sharding value
     * @return sharding results for data sources or tables's names
     */
    @Override
    public Collection doSharding(Collection availableTargetNames, RangeShardingValue shardingValue) {
        String tableName = "tb_order";
        Range range = shardingValue.getValueRange();
        Date startDate = range.lowerEndpoint();
        Date endDate = range.upperEndpoint();
        if(endDate.after(new Date())){
            endDate = new Date();
        }
        Set dateSet = new HashSet<>();
        dateSet.add(tableName);
        for(;startDate.before(endDate);startDate = DateUtils.dateAdd(DateUtils.DATE_INTERVAL_DAY,startDate,1)){
            String sdValue = DateUtils.format(startDate,"yyyyMMddHHmmss");
            if(StringUtils.isNotBlank(sdValue) && sdValue.length()>6){
                dateSet.add(tableName+sdValue.substring(0,6));
            }

        }
        return dateSet;
    }
}

OK,这样就全部代码,接下来可以写方法进行测试。由于是根据支付时间分表的,直接写个简单查询。

 /**
     * 根据支付时间查询订单
     * @param payStartDate
     * @param payEndDate
     * @return
     */
    List selectOrderListByPayAt1(@Param("payStartDate") Date payStartDate, @Param("payEndDate") Date payEndDate);

    @ResponseBody
    @RequestMapping(value = "/test",method = RequestMethod.GET)
    public String sendMsgToKafka(){
        Date endDate = new Date();
        Date startDate = DateUtils.dateAdd(DateUtils.DATE_INTERVAL_DAY,endDate,-30);
        List order = orderMapper.selectOrderListByPayAt1(startDate,endDate);
        return JSON.toJSONString("订单信息="+JSON.toJSONString(order));
    }

可以直接运行一切OK。

三、接入遇到的坑

1、最开始我接入的时候,没有指定实际数据表,运行时一致报错有两个数据源。最后检查了半天是这个问题。

2、由于是按照时间分片,需要按照范围查找的,所有又重写了范围分片算法。

3、可以写个定时任务每月建一张表。

4、把事务等数据源都改为:shardingDataSource

四、结论

在引入第三方插件时,建议仔细看官方文档和源码,不要病急乱投医。不是有句古话:磨刀不如砍柴工。别人的东西是挺省事,关键是要适合自己。特此记录下来,供以后学习参考,方便自己与方便他人,何乐而不为!

你可能感兴趣的:(数据库,学习,mybatis)