Parcourir la source

修改分库分表逻辑

lc il y a 1 semaine
Parent
commit
4fe0f3974d

+ 51 - 291
mall-service/src/main/java/com/txz/mall/configurer/DatabaseShardingAlgorithm.java

@@ -1,16 +1,14 @@
 package com.txz.mall.configurer;
 
 import com.alibaba.fastjson.JSONObject;
-import com.google.common.collect.Range;
 import com.txz.mall.util.I18nUtil;
+import com.txz.mall.util.OrderUtils;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
-import org.springframework.util.ObjectUtils;
 
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
 
 public class DatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
 
@@ -318,296 +316,58 @@ public class DatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<C
 //    }
 
 
-    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-    private static final SimpleDateFormat SDF_ORDER_NO = new SimpleDateFormat("yyyyMMdd");
-    private static final Set<Integer> FIRST_HALF_MONTHS = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6));
-    private static final Set<Integer> SECOND_HALF_MONTHS = new HashSet<>(Arrays.asList(7, 8, 9, 10, 11, 12));
-
-    @Override
-    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 优先处理order_id IN条件
-        Map<String, List<Long>> orderIdDbMap = getOrderIdDbMap(shardingValue);
-        if (!orderIdDbMap.isEmpty()) {
-            Set<String> targetDbs = new HashSet<>();
-            for (List<Long> params : orderIdDbMap.values()) {
-                Date createTime = new Date(params.get(0));
-                Long userId = params.get(1);
-                targetDbs.addAll(routeByTimeAndUserId(availableTargets, createTime, userId));
-            }
-            return targetDbs.isEmpty() ? availableTargets : targetDbs;
-        }
-
-        // 处理无order_id的情况(如uid+create_time范围)
-        return handleNonOrderIdSharding(availableTargets, shardingValue);
-    }
-
-    /**
-     * 解析所有order_id,提取时间和用户ID
-     */
-    private Map<String, List<Long>> getOrderIdDbMap(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        Map<String, List<Long>> result = new HashMap<>();
-
-        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
-            for (Comparable<?> val : values.get("order_id")) {
-                String orderId = (String) val;
-                try {
-                    String dateStr = "20" + orderId.substring(2, 8);
-                    Date createTime = SDF_ORDER_NO.parse(dateStr);
-                    String lastFour = orderId.substring(orderId.length() - 4);
-                    Long userId = Long.parseLong(lastFour);
-                    result.put(orderId, Arrays.asList(createTime.getTime(), userId));
-                } catch (ParseException | StringIndexOutOfBoundsException e) {
-                    throw new RuntimeException(I18nUtil.get("failed.to.parse.the.sharding.condition.for.order.id") + JSONObject.toJSONString(shardingValue), e);
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * 处理无order_id的情况(支持create_time范围查询)
-     */
-    private Collection<String> handleNonOrderIdSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 提取create_time的范围(start和end)
-        DateRange createTimeRange = getCreateTimeRange(shardingValue);
-        Long userId = getUserId(shardingValue);
-
-        // 有时间范围时,按范围路由
-        if (createTimeRange != null) {
-            Set<String> targetDbs = new HashSet<>();
-            // 判断是否与1-6月重叠
-            if (isRangeOverlapFirstHalf(createTimeRange)) {
-                targetDbs.addAll(routeFirstHalf(availableTargets, userId));
-            }
-            // 判断是否与7-12月重叠
-            if (isRangeOverlapSecondHalf(createTimeRange)) {
-                targetDbs.addAll(routeSecondHalf(availableTargets, userId));
-            }
-            return targetDbs.isEmpty() ? availableTargets : targetDbs;
-        }
-
-        // 无时间范围时,全库扫描
-        return filterAllDatabases(availableTargets, userId);
-    }
-
-    /**
-     * 提取create_time的范围值(支持>=和<=)
-     */
-    private DateRange getCreateTimeRange(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 1. 从范围条件集合中获取create_time的范围值
-        Map<String, com.google.common.collect.Range<Comparable<?>>> rangeValuesMap = shardingValue.getColumnNameAndRangeValuesMap();
-        com.google.common.collect.Range<Comparable<?>> createTimeRanges = rangeValuesMap.get("create_time");
-
-        Date start = null;
-        Date end = null;
-        // 若没有create_time的范围条件,返回null
-//        if (createTimeRanges == null || createTimeRanges.isEmpty()) {
-//            return null;
-//        }
-        if(!ObjectUtils.isEmpty(createTimeRanges)){
-            if (createTimeRanges.hasLowerBound()) {
-                Comparable<?> lowerVal = createTimeRanges.lowerEndpoint();
-                start = parseDate(lowerVal);
-            }
-            // 提取上界(<=)
-            if (createTimeRanges.hasUpperBound()) {
-                Comparable<?> upperVal = createTimeRanges.upperEndpoint();
-                end = parseDate(upperVal);
-            }
-        }
-
-
-        // 3. 兼容等值条件(如果存在create_time = ?,从精确值中提取)
-        if (start == null && end == null) {
-            Map<String, Collection<Comparable<?>>> preciseValuesMap = shardingValue.getColumnNameAndShardingValuesMap();
-            Collection<Comparable<?>> createTimePrecise = preciseValuesMap.get("create_time");
-            if (createTimePrecise != null && !createTimePrecise.isEmpty()) {
-                Comparable<?> preciseVal = createTimePrecise.iterator().next();
-                Date date = parseDate(preciseVal);
-                start = date;
-                end = date;
-            }
-        }
-
-        return (start != null || end != null) ? new DateRange(start, end) : null;
-    }
-
-    /**
-     * 判断时间范围是否与1-6月重叠
-     */
-    private boolean isRangeOverlapFirstHalf(DateRange range) {
-        Calendar firstHalfStart = Calendar.getInstance();
-        firstHalfStart.set(Calendar.MONTH, 0); // 1月
-        firstHalfStart.set(Calendar.DAY_OF_MONTH, 1);
-        firstHalfStart.set(Calendar.HOUR_OF_DAY, 0);
-        firstHalfStart.set(Calendar.MINUTE, 0);
-        firstHalfStart.set(Calendar.SECOND, 0);
-
-        Calendar firstHalfEnd = Calendar.getInstance();
-        firstHalfEnd.set(Calendar.MONTH, 5); // 6月
-        firstHalfEnd.set(Calendar.DAY_OF_MONTH, 30);
-        firstHalfEnd.set(Calendar.HOUR_OF_DAY, 23);
-        firstHalfEnd.set(Calendar.MINUTE, 59);
-        firstHalfEnd.set(Calendar.SECOND, 59);
-
-        return isOverlap(range, new DateRange(firstHalfStart.getTime(), firstHalfEnd.getTime()));
-    }
-
-    /**
-     * 判断时间范围是否与7-12月重叠
-     */
-    private boolean isRangeOverlapSecondHalf(DateRange range) {
-        Calendar secondHalfStart = Calendar.getInstance();
-        secondHalfStart.set(Calendar.MONTH, 6); // 7月
-        secondHalfStart.set(Calendar.DAY_OF_MONTH, 1);
-        secondHalfStart.set(Calendar.HOUR_OF_DAY, 0);
-        secondHalfStart.set(Calendar.MINUTE, 0);
-        secondHalfStart.set(Calendar.SECOND, 0);
-
-        Calendar secondHalfEnd = Calendar.getInstance();
-        secondHalfEnd.set(Calendar.MONTH, 11); // 12月
-        secondHalfEnd.set(Calendar.DAY_OF_MONTH, 31);
-        secondHalfEnd.set(Calendar.HOUR_OF_DAY, 23);
-        secondHalfEnd.set(Calendar.MINUTE, 59);
-        secondHalfEnd.set(Calendar.SECOND, 59);
-
-        return isOverlap(range, new DateRange(secondHalfStart.getTime(), secondHalfEnd.getTime()));
-    }
-
-    /**
-     * 判断两个时间范围是否重叠
-     */
-    private boolean isOverlap(DateRange range1, DateRange range2) {
-        // 范围1在范围2之前(不重叠)
-        if (range1.getEnd() != null && range2.getStart() != null
-                && range1.getEnd().before(range2.getStart())) {
-            return false;
-        }
-        // 范围1在范围2之后(不重叠)
-        if (range1.getStart() != null && range2.getEnd() != null
-                && range1.getStart().after(range2.getEnd())) {
-            return false;
-        }
-        // 其他情况均重叠
-        return true;
-    }
+  // 步骤1:修改getUserId,返回所有order_id对应的分表键(后4位)
+  private Collection<Long> getShardingKeys(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+    Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
+    Collection<Long> shardingKeys = new ArrayList<>();
 
-    /**
-     * 根据时间和用户ID路由数据库
-     */
-    private Collection<String> routeByTimeAndUserId(Collection<String> availableTargets, Date createTime, Long userId) {
-        if (isFirstHalfYear(createTime)) {
-            return routeFirstHalf(availableTargets, userId);
-        } else if (isSecondHalfYear(createTime)) {
-            return routeSecondHalf(availableTargets, userId);
-        }
-        return availableTargets;
+    // 优先处理uid(如果有)
+    if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
+      for (Comparable<?> val : values.get("uid")) {
+        Long uid = (Long) val;
+        shardingKeys.add(Long.parseLong(OrderUtils.getLastFourDigitsOfTheUserId(uid)));
+      }
+      return shardingKeys;
     }
 
-    /**
-     * 1-6月路由(ds0/ds1)
-     */
-    private Collection<String> routeFirstHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            long dbIndex = userId % 2;
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        return Arrays.asList("ds0", "ds1");
-    }
-
-    /**
-     * 7-12月路由(ds2/ds3)
-     */
-    private Collection<String> routeSecondHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            long dbIndex = 2 + (userId % 2); // 2或3
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        return Arrays.asList("ds2", "ds3");
+    // 核心:处理order_id
+    if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
+      for (Comparable<?> val : values.get("order_id")) {
+        String orderId = (String) val;
+        // 提取每个order_id的后4位,作为分表键
+        String lastFourStr = orderId.substring(orderId.length() - 4);
+        shardingKeys.add(Long.parseLong(lastFourStr));
+      }
+      return shardingKeys;
     }
 
-    /**
-     * 提取uid(非order_id场景)
-     */
-    private Long getUserId(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
-            Long uid = (Long) values.get("uid").iterator().next();
-            return uid % 10000;
-        }
-        return null;
-    }
-
-    /**
-     * 判断是否为1-6月
-     */
-    private boolean isFirstHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return FIRST_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    /**
-     * 判断是否为7-12月
-     */
-    private boolean isSecondHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return SECOND_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    /**
-     * 无时间条件时的全库过滤
-     */
-    private Collection<String> filterAllDatabases(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            return Arrays.asList("ds0", "ds1", "ds2", "ds3");
-        }
-        return availableTargets;
-    }
-
-    /**
-     * 解析时间对象为Date
-     */
-    private Date parseDate(Object value) {
-        if (value instanceof Date) {
-            return (Date) value;
-        }
-        try {
-            return SDF.parse(value.toString());
-        } catch (ParseException e) {
-            throw new RuntimeException(I18nUtil.get("time.format.error") + value, e);
-        }
-    }
-
-    /**
-     * 内部类:表示时间范围(start <= create_time <= end)
-     */
-    private static class DateRange {
-        private final Date start;
-        private final Date end;
-
-        public DateRange(Date start, Date end) {
-            this.start = start;
-            this.end = end;
-        }
-
-        public Date getStart() {
-            return start;
-        }
-
-        public Date getEnd() {
-            return end;
+    return shardingKeys;
+  }
+    @Override
+    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+      // 1. 获取所有分表键(每个order_id对应一个)
+      Collection<Long> shardingKeys = getShardingKeys(shardingValue);
+      if (shardingKeys.isEmpty()) {
+        throw new IllegalArgumentException(I18nUtil.get("the.partition.key.cannot.be.empty.must.include.either.uid.or.order.id")+ JSONObject.toJSONString(shardingValue));
+      }
+      // 2. 每个分表键对应一个表,收集所有匹配的表
+      Collection<String> resultTables = new ArrayList<>();
+      for (Long key : shardingKeys) {
+        // 计算分区(和你原逻辑一致:key % 5)
+        long tableSuffix = (int) Math.floorMod(key, 4);
+        // 匹配可用表(如m_store_pink_3)
+        for (String targetTable : availableTargets) {
+          if (targetTable.endsWith(String.valueOf(tableSuffix))) {
+            resultTables.add(targetTable);
+            break; // 找到对应表就跳出,避免重复
+          }
         }
-    }
-
-
+      }
+      // 3. 若没有匹配的表,抛出异常
+      if (resultTables.isEmpty()) {
+        throw new IllegalArgumentException(I18nUtil.get("no.matching.table.found") + availableTargets + I18nUtil.get("table.key") + shardingKeys);
+      }
+      return resultTables;
+  }
 
 }

+ 10 - 13
mall-service/src/main/java/com/txz/mall/configurer/ShardingJdbcConfig.java

@@ -1,25 +1,22 @@
 package com.txz.mall.configurer;
 
-import com.zaxxer.hikari.HikariConfig;
 import com.zaxxer.hikari.HikariDataSource;
-import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
 import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
 import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
 import org.apache.shardingsphere.api.config.sharding.strategy.ComplexShardingStrategyConfiguration;
-import org.apache.shardingsphere.api.config.sharding.strategy.StandardShardingStrategyConfiguration;
 import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.transaction.PlatformTransactionManager;
 
 import javax.sql.DataSource;
 import java.sql.SQLException;
-import java.util.*;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
 
 @Configuration
 public class ShardingJdbcConfig {
@@ -256,7 +253,7 @@ public class ShardingJdbcConfig {
 
         orderTableRule.setDatabaseShardingStrategyConfig(
                 new ComplexShardingStrategyConfiguration(
-                        "create_time,uid,order_id",  // 多分片键
+                        "uid,order_id",  // 多分片键
                         new DatabaseShardingAlgorithm()      // 复合分片算法
                 )
         );
@@ -277,7 +274,7 @@ public class ShardingJdbcConfig {
 
         orderTableRule.setDatabaseShardingStrategyConfig(
                 new ComplexShardingStrategyConfiguration(
-                        "create_time,uid,order_id",  // 多分片键
+                        "uid,order_id",  // 多分片键
                         new DatabaseShardingAlgorithm()      // 复合分片算法
                 )
         );
@@ -366,13 +363,13 @@ public class ShardingJdbcConfig {
 
         orderTableRule.setDatabaseShardingStrategyConfig(
                 new ComplexShardingStrategyConfiguration(
-                        "uid,create_day",  // 多分片键
+                        "uid",  // 多分片键
                         new UserSignDatabaseShardingAlgorithm()      // 复合分片算法
                 )
         );
         orderTableRule.setTableShardingStrategyConfig(
                 new ComplexShardingStrategyConfiguration(
-                        "uid,create_day",  // 多分片键
+                        "uid",  // 多分片键
                         new UserSignTableShardingAlgorithm()      // 复合分片算法
                 )
         );

+ 16 - 265
mall-service/src/main/java/com/txz/mall/configurer/StoreOrderInfoDatabaseShardingAlgorithm.java

@@ -163,46 +163,44 @@ public class StoreOrderInfoDatabaseShardingAlgorithm implements ComplexKeysShard
 //        return availableTargets;
 //    }
 //
-private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-    private static final SimpleDateFormat SDF_ORDER_NO = new SimpleDateFormat("yyyyMMdd");
-    private static final Set<Integer> FIRST_HALF_MONTHS = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6));
-    private static final Set<Integer> SECOND_HALF_MONTHS = new HashSet<>(Arrays.asList(7, 8, 9, 10, 11, 12));
-
     @Override
     public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
         // 优先处理order_id IN条件
-        Map<String, List<Long>> orderIdDbMap = getOrderIdDbMap(shardingValue);
+        Collection<Long> orderIdDbMap = getOrderIdDbMap(shardingValue);
         if (!orderIdDbMap.isEmpty()) {
             Set<String> targetDbs = new HashSet<>();
-            for (List<Long> params : orderIdDbMap.values()) {
-                Date createTime = new Date(params.get(0));
-                Long userId = params.get(1);
-                targetDbs.addAll(routeByTimeAndUserId(availableTargets, createTime, userId));
+            for (Long key : orderIdDbMap) {
+              // 计算分区(和你原逻辑一致:key % 5)
+              long tableSuffix = (int) Math.floorMod(key, 4);
+              // 匹配可用表(如m_store_pink_3)
+              for (String targetTable : availableTargets) {
+                if (targetTable.endsWith(String.valueOf(tableSuffix))) {
+                  targetDbs.add(targetTable);
+                  break; // 找到对应表就跳出,避免重复
+                }
+              }
             }
             return targetDbs.isEmpty() ? availableTargets : targetDbs;
         }
-
         // 处理无order_id的情况(如uid+create_time范围)
-        return handleNonOrderIdSharding(availableTargets, shardingValue);
+       return availableTargets;
     }
 
     /**
      * 解析所有order_id,提取时间和用户ID
      */
-    private Map<String, List<Long>> getOrderIdDbMap(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+    private Collection<Long> getOrderIdDbMap(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
         Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        Map<String, List<Long>> result = new HashMap<>();
+        Collection<Long> result = new ArrayList<>();
 
         if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
             for (Comparable<?> val : values.get("order_no")) {
                 String orderId = (String) val;
                 try {
-                    String dateStr = "20" + orderId.substring(2, 8);
-                    Date createTime = SDF_ORDER_NO.parse(dateStr);
                     String lastFour = orderId.substring(orderId.length() - 4);
                     Long userId = Long.parseLong(lastFour);
-                    result.put(orderId, Arrays.asList(createTime.getTime(), userId));
-                } catch (ParseException | StringIndexOutOfBoundsException e) {
+                    result.add(userId);
+                } catch (StringIndexOutOfBoundsException e) {
                     throw new RuntimeException(I18nUtil.get("failed.to.parse.the.sharding.condition.for.order.id") + JSONObject.toJSONString(shardingValue), e);
                 }
             }
@@ -210,251 +208,4 @@ private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:
         return result;
     }
 
-    /**
-     * 处理无order_id的情况(支持create_time范围查询)
-     */
-    private Collection<String> handleNonOrderIdSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 提取create_time的范围(start和end)
-        StoreOrderInfoDatabaseShardingAlgorithm.DateRange createTimeRange = getCreateTimeRange(shardingValue);
-        Long userId = getUserId(shardingValue);
-
-        // 有时间范围时,按范围路由
-        if (createTimeRange != null) {
-            Set<String> targetDbs = new HashSet<>();
-            // 判断是否与1-6月重叠
-            if (isRangeOverlapFirstHalf(createTimeRange)) {
-                targetDbs.addAll(routeFirstHalf(availableTargets, userId));
-            }
-            // 判断是否与7-12月重叠
-            if (isRangeOverlapSecondHalf(createTimeRange)) {
-                targetDbs.addAll(routeSecondHalf(availableTargets, userId));
-            }
-            return targetDbs.isEmpty() ? availableTargets : targetDbs;
-        }
-
-        // 无时间范围时,全库扫描
-        return filterAllDatabases(availableTargets, userId);
-    }
-
-    /**
-     * 提取create_time的范围值(支持>=和<=)
-     */
-    private StoreOrderInfoDatabaseShardingAlgorithm.DateRange getCreateTimeRange(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 1. 从范围条件集合中获取create_time的范围值
-        Map<String, com.google.common.collect.Range<Comparable<?>>> rangeValuesMap = shardingValue.getColumnNameAndRangeValuesMap();
-        com.google.common.collect.Range<Comparable<?>> createTimeRanges = rangeValuesMap.get("create_time");
-
-        Date start = null;
-        Date end = null;
-        // 若没有create_time的范围条件,返回null
-//        if (createTimeRanges == null || createTimeRanges.isEmpty()) {
-//            return null;
-//        }
-        if(!ObjectUtils.isEmpty(createTimeRanges)){
-            if (createTimeRanges.hasLowerBound()) {
-                Comparable<?> lowerVal = createTimeRanges.lowerEndpoint();
-                start = parseDate(lowerVal);
-            }
-            // 提取上界(<=)
-            if (createTimeRanges.hasUpperBound()) {
-                Comparable<?> upperVal = createTimeRanges.upperEndpoint();
-                end = parseDate(upperVal);
-            }
-        }
-
-
-        // 3. 兼容等值条件(如果存在create_time = ?,从精确值中提取)
-        if (start == null && end == null) {
-            Map<String, Collection<Comparable<?>>> preciseValuesMap = shardingValue.getColumnNameAndShardingValuesMap();
-            Collection<Comparable<?>> createTimePrecise = preciseValuesMap.get("create_time");
-            if (createTimePrecise != null && !createTimePrecise.isEmpty()) {
-                Comparable<?> preciseVal = createTimePrecise.iterator().next();
-                Date date = parseDate(preciseVal);
-                start = date;
-                end = date;
-            }
-        }
-
-        return (start != null || end != null) ? new StoreOrderInfoDatabaseShardingAlgorithm.DateRange(start, end) : null;
-    }
-
-    /**
-     * 判断时间范围是否与1-6月重叠
-     */
-    private boolean isRangeOverlapFirstHalf(StoreOrderInfoDatabaseShardingAlgorithm.DateRange range) {
-        Calendar firstHalfStart = Calendar.getInstance();
-        firstHalfStart.set(Calendar.MONTH, 0); // 1月
-        firstHalfStart.set(Calendar.DAY_OF_MONTH, 1);
-        firstHalfStart.set(Calendar.HOUR_OF_DAY, 0);
-        firstHalfStart.set(Calendar.MINUTE, 0);
-        firstHalfStart.set(Calendar.SECOND, 0);
-
-        Calendar firstHalfEnd = Calendar.getInstance();
-        firstHalfEnd.set(Calendar.MONTH, 5); // 6月
-        firstHalfEnd.set(Calendar.DAY_OF_MONTH, 30);
-        firstHalfEnd.set(Calendar.HOUR_OF_DAY, 23);
-        firstHalfEnd.set(Calendar.MINUTE, 59);
-        firstHalfEnd.set(Calendar.SECOND, 59);
-
-        return isOverlap(range, new StoreOrderInfoDatabaseShardingAlgorithm.DateRange(firstHalfStart.getTime(), firstHalfEnd.getTime()));
-    }
-
-    /**
-     * 判断时间范围是否与7-12月重叠
-     */
-    private boolean isRangeOverlapSecondHalf(StoreOrderInfoDatabaseShardingAlgorithm.DateRange range) {
-        Calendar secondHalfStart = Calendar.getInstance();
-        secondHalfStart.set(Calendar.MONTH, 6); // 7月
-        secondHalfStart.set(Calendar.DAY_OF_MONTH, 1);
-        secondHalfStart.set(Calendar.HOUR_OF_DAY, 0);
-        secondHalfStart.set(Calendar.MINUTE, 0);
-        secondHalfStart.set(Calendar.SECOND, 0);
-
-        Calendar secondHalfEnd = Calendar.getInstance();
-        secondHalfEnd.set(Calendar.MONTH, 11); // 12月
-        secondHalfEnd.set(Calendar.DAY_OF_MONTH, 31);
-        secondHalfEnd.set(Calendar.HOUR_OF_DAY, 23);
-        secondHalfEnd.set(Calendar.MINUTE, 59);
-        secondHalfEnd.set(Calendar.SECOND, 59);
-
-        return isOverlap(range, new StoreOrderInfoDatabaseShardingAlgorithm.DateRange(secondHalfStart.getTime(), secondHalfEnd.getTime()));
-    }
-
-    /**
-     * 判断两个时间范围是否重叠
-     */
-    private boolean isOverlap(StoreOrderInfoDatabaseShardingAlgorithm.DateRange range1, StoreOrderInfoDatabaseShardingAlgorithm.DateRange range2) {
-        // 范围1在范围2之前(不重叠)
-        if (range1.getEnd() != null && range2.getStart() != null
-                && range1.getEnd().before(range2.getStart())) {
-            return false;
-        }
-        // 范围1在范围2之后(不重叠)
-        if (range1.getStart() != null && range2.getEnd() != null
-                && range1.getStart().after(range2.getEnd())) {
-            return false;
-        }
-        // 其他情况均重叠
-        return true;
-    }
-
-    /**
-     * 根据时间和用户ID路由数据库
-     */
-    private Collection<String> routeByTimeAndUserId(Collection<String> availableTargets, Date createTime, Long userId) {
-        if (isFirstHalfYear(createTime)) {
-            return routeFirstHalf(availableTargets, userId);
-        } else if (isSecondHalfYear(createTime)) {
-            return routeSecondHalf(availableTargets, userId);
-        }
-        return availableTargets;
-    }
-
-    /**
-     * 1-6月路由(ds0/ds1)
-     */
-    private Collection<String> routeFirstHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            long dbIndex = userId % 2;
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        return Arrays.asList("ds0", "ds1");
-    }
-
-    /**
-     * 7-12月路由(ds2/ds3)
-     */
-    private Collection<String> routeSecondHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            long dbIndex = 2 + (userId % 2); // 2或3
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        return Arrays.asList("ds2", "ds3");
-    }
-
-    /**
-     * 提取uid(非order_id场景)
-     */
-    private Long getUserId(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
-            Long uid = (Long) values.get("uid").iterator().next();
-            return uid % 10000;
-        }
-        return null;
-    }
-
-    /**
-     * 判断是否为1-6月
-     */
-    private boolean isFirstHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return FIRST_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    /**
-     * 判断是否为7-12月
-     */
-    private boolean isSecondHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return SECOND_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    /**
-     * 无时间条件时的全库过滤
-     */
-    private Collection<String> filterAllDatabases(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            return Arrays.asList("ds0", "ds1", "ds2", "ds3");
-        }
-        return availableTargets;
-    }
-
-    /**
-     * 解析时间对象为Date
-     */
-    private Date parseDate(Object value) {
-        if (value instanceof Date) {
-            return (Date) value;
-        }
-        try {
-            return SDF.parse(value.toString());
-        } catch (ParseException e) {
-            throw new RuntimeException(I18nUtil.get("time.format.error") + value, e);
-        }
-    }
-
-    /**
-     * 内部类:表示时间范围(start <= create_time <= end)
-     */
-    private static class DateRange {
-        private final Date start;
-        private final Date end;
-
-        public DateRange(Date start, Date end) {
-            this.start = start;
-            this.end = end;
-        }
-
-        public Date getStart() {
-            return start;
-        }
-
-        public Date getEnd() {
-            return end;
-        }
-    }
-
-
-
-
-
 }

+ 16 - 270
mall-service/src/main/java/com/txz/mall/configurer/StoreOrderStatusDatabaseShardingAlgorithm.java

@@ -4,10 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.txz.mall.util.I18nUtil;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
-import org.springframework.util.ObjectUtils;
 
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.*;
 
 public class StoreOrderStatusDatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
@@ -163,47 +160,43 @@ public class StoreOrderStatusDatabaseShardingAlgorithm implements ComplexKeysSha
 //        return availableTargets;
 //    }
 
-
-    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-    private static final SimpleDateFormat SDF_ORDER_NO = new SimpleDateFormat("yyyyMMdd");
-    private static final Set<Integer> FIRST_HALF_MONTHS = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6));
-    private static final Set<Integer> SECOND_HALF_MONTHS = new HashSet<>(Arrays.asList(7, 8, 9, 10, 11, 12));
-
     @Override
     public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
         // 优先处理order_id IN条件
-        Map<String, List<Long>> orderIdDbMap = getOrderIdDbMap(shardingValue);
+        Collection<Long> orderIdDbMap = getOrderIdDbMap(shardingValue);
         if (!orderIdDbMap.isEmpty()) {
             Set<String> targetDbs = new HashSet<>();
-            for (List<Long> params : orderIdDbMap.values()) {
-                Date createTime = new Date(params.get(0));
-                Long userId = params.get(1);
-                targetDbs.addAll(routeByTimeAndUserId(availableTargets, createTime, userId));
+            for (Long params : orderIdDbMap) {
+              // 计算分区(和你原逻辑一致:key % 5)
+              long tableSuffix = (int) Math.floorMod(params, 4);
+              // 匹配可用表(如m_store_pink_3)
+              for (String targetTable : availableTargets) {
+                if (targetTable.endsWith(String.valueOf(tableSuffix))) {
+                  targetDbs.add(targetTable);
+                  break; // 找到对应表就跳出,避免重复
+                }
+              }
             }
             return targetDbs.isEmpty() ? availableTargets : targetDbs;
         }
-
-        // 处理无order_id的情况(如uid+create_time范围)
-        return handleNonOrderIdSharding(availableTargets, shardingValue);
+        return availableTargets;
     }
 
     /**
      * 解析所有order_id,提取时间和用户ID
      */
-    private Map<String, List<Long>> getOrderIdDbMap(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+    private Collection<Long> getOrderIdDbMap(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
         Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        Map<String, List<Long>> result = new HashMap<>();
+         Collection<Long> result = new ArrayList<>();
 
         if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
             for (Comparable<?> val : values.get("order_id")) {
                 String orderId = (String) val;
                 try {
-                    String dateStr = "20" + orderId.substring(2, 8);
-                    Date createTime = SDF_ORDER_NO.parse(dateStr);
                     String lastFour = orderId.substring(orderId.length() - 4);
                     Long userId = Long.parseLong(lastFour);
-                    result.put(orderId, Arrays.asList(createTime.getTime(), userId));
-                } catch (ParseException | StringIndexOutOfBoundsException e) {
+                    result.add(userId);
+                } catch (StringIndexOutOfBoundsException e) {
                     throw new RuntimeException(I18nUtil.get("failed.to.parse.the.sharding.condition.for.order.id") + JSONObject.toJSONString(shardingValue), e);
                 }
             }
@@ -211,251 +204,4 @@ public class StoreOrderStatusDatabaseShardingAlgorithm implements ComplexKeysSha
         return result;
     }
 
-    /**
-     * 处理无order_id的情况(支持create_time范围查询)
-     */
-    private Collection<String> handleNonOrderIdSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 提取create_time的范围(start和end)
-        StoreOrderStatusDatabaseShardingAlgorithm.DateRange createTimeRange = getCreateTimeRange(shardingValue);
-        Long userId = getUserId(shardingValue);
-
-        // 有时间范围时,按范围路由
-        if (createTimeRange != null) {
-            Set<String> targetDbs = new HashSet<>();
-            // 判断是否与1-6月重叠
-            if (isRangeOverlapFirstHalf(createTimeRange)) {
-                targetDbs.addAll(routeFirstHalf(availableTargets, userId));
-            }
-            // 判断是否与7-12月重叠
-            if (isRangeOverlapSecondHalf(createTimeRange)) {
-                targetDbs.addAll(routeSecondHalf(availableTargets, userId));
-            }
-            return targetDbs.isEmpty() ? availableTargets : targetDbs;
-        }
-
-        // 无时间范围时,全库扫描
-        return filterAllDatabases(availableTargets, userId);
-    }
-
-    /**
-     * 提取create_time的范围值(支持>=和<=)
-     */
-    private StoreOrderStatusDatabaseShardingAlgorithm.DateRange getCreateTimeRange(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        // 1. 从范围条件集合中获取create_time的范围值
-        Map<String, com.google.common.collect.Range<Comparable<?>>> rangeValuesMap = shardingValue.getColumnNameAndRangeValuesMap();
-        com.google.common.collect.Range<Comparable<?>> createTimeRanges = rangeValuesMap.get("create_time");
-
-        Date start = null;
-        Date end = null;
-        // 若没有create_time的范围条件,返回null
-//        if (createTimeRanges == null || createTimeRanges.isEmpty()) {
-//            return null;
-//        }
-        if(!ObjectUtils.isEmpty(createTimeRanges)){
-            if (createTimeRanges.hasLowerBound()) {
-                Comparable<?> lowerVal = createTimeRanges.lowerEndpoint();
-                start = parseDate(lowerVal);
-            }
-            // 提取上界(<=)
-            if (createTimeRanges.hasUpperBound()) {
-                Comparable<?> upperVal = createTimeRanges.upperEndpoint();
-                end = parseDate(upperVal);
-            }
-        }
-
-
-        // 3. 兼容等值条件(如果存在create_time = ?,从精确值中提取)
-        if (start == null && end == null) {
-            Map<String, Collection<Comparable<?>>> preciseValuesMap = shardingValue.getColumnNameAndShardingValuesMap();
-            Collection<Comparable<?>> createTimePrecise = preciseValuesMap.get("create_time");
-            if (createTimePrecise != null && !createTimePrecise.isEmpty()) {
-                Comparable<?> preciseVal = createTimePrecise.iterator().next();
-                Date date = parseDate(preciseVal);
-                start = date;
-                end = date;
-            }
-        }
-
-        return (start != null || end != null) ? new StoreOrderStatusDatabaseShardingAlgorithm.DateRange(start, end) : null;
-    }
-
-    /**
-     * 判断时间范围是否与1-6月重叠
-     */
-    private boolean isRangeOverlapFirstHalf(StoreOrderStatusDatabaseShardingAlgorithm.DateRange range) {
-        Calendar firstHalfStart = Calendar.getInstance();
-        firstHalfStart.set(Calendar.MONTH, 0); // 1月
-        firstHalfStart.set(Calendar.DAY_OF_MONTH, 1);
-        firstHalfStart.set(Calendar.HOUR_OF_DAY, 0);
-        firstHalfStart.set(Calendar.MINUTE, 0);
-        firstHalfStart.set(Calendar.SECOND, 0);
-
-        Calendar firstHalfEnd = Calendar.getInstance();
-        firstHalfEnd.set(Calendar.MONTH, 5); // 6月
-        firstHalfEnd.set(Calendar.DAY_OF_MONTH, 30);
-        firstHalfEnd.set(Calendar.HOUR_OF_DAY, 23);
-        firstHalfEnd.set(Calendar.MINUTE, 59);
-        firstHalfEnd.set(Calendar.SECOND, 59);
-
-        return isOverlap(range, new StoreOrderStatusDatabaseShardingAlgorithm.DateRange(firstHalfStart.getTime(), firstHalfEnd.getTime()));
-    }
-
-    /**
-     * 判断时间范围是否与7-12月重叠
-     */
-    private boolean isRangeOverlapSecondHalf(StoreOrderStatusDatabaseShardingAlgorithm.DateRange range) {
-        Calendar secondHalfStart = Calendar.getInstance();
-        secondHalfStart.set(Calendar.MONTH, 6); // 7月
-        secondHalfStart.set(Calendar.DAY_OF_MONTH, 1);
-        secondHalfStart.set(Calendar.HOUR_OF_DAY, 0);
-        secondHalfStart.set(Calendar.MINUTE, 0);
-        secondHalfStart.set(Calendar.SECOND, 0);
-
-        Calendar secondHalfEnd = Calendar.getInstance();
-        secondHalfEnd.set(Calendar.MONTH, 11); // 12月
-        secondHalfEnd.set(Calendar.DAY_OF_MONTH, 31);
-        secondHalfEnd.set(Calendar.HOUR_OF_DAY, 23);
-        secondHalfEnd.set(Calendar.MINUTE, 59);
-        secondHalfEnd.set(Calendar.SECOND, 59);
-
-        return isOverlap(range, new StoreOrderStatusDatabaseShardingAlgorithm.DateRange(secondHalfStart.getTime(), secondHalfEnd.getTime()));
-    }
-
-    /**
-     * 判断两个时间范围是否重叠
-     */
-    private boolean isOverlap(StoreOrderStatusDatabaseShardingAlgorithm.DateRange range1, StoreOrderStatusDatabaseShardingAlgorithm.DateRange range2) {
-        // 范围1在范围2之前(不重叠)
-        if (range1.getEnd() != null && range2.getStart() != null
-                && range1.getEnd().before(range2.getStart())) {
-            return false;
-        }
-        // 范围1在范围2之后(不重叠)
-        if (range1.getStart() != null && range2.getEnd() != null
-                && range1.getStart().after(range2.getEnd())) {
-            return false;
-        }
-        // 其他情况均重叠
-        return true;
-    }
-
-    /**
-     * 根据时间和用户ID路由数据库
-     */
-    private Collection<String> routeByTimeAndUserId(Collection<String> availableTargets, Date createTime, Long userId) {
-        if (isFirstHalfYear(createTime)) {
-            return routeFirstHalf(availableTargets, userId);
-        } else if (isSecondHalfYear(createTime)) {
-            return routeSecondHalf(availableTargets, userId);
-        }
-        return availableTargets;
-    }
-
-    /**
-     * 1-6月路由(ds0/ds1)
-     */
-    private Collection<String> routeFirstHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            long dbIndex = userId % 2;
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        return Arrays.asList("ds0", "ds1");
-    }
-
-    /**
-     * 7-12月路由(ds2/ds3)
-     */
-    private Collection<String> routeSecondHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            long dbIndex = 2 + (userId % 2); // 2或3
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        return Arrays.asList("ds2", "ds3");
-    }
-
-    /**
-     * 提取uid(非order_id场景)
-     */
-    private Long getUserId(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
-            Long uid = (Long) values.get("uid").iterator().next();
-            return uid % 10000;
-        }
-        return null;
-    }
-
-    /**
-     * 判断是否为1-6月
-     */
-    private boolean isFirstHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return FIRST_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    /**
-     * 判断是否为7-12月
-     */
-    private boolean isSecondHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return SECOND_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    /**
-     * 无时间条件时的全库过滤
-     */
-    private Collection<String> filterAllDatabases(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            return Arrays.asList("ds0", "ds1", "ds2", "ds3");
-        }
-        return availableTargets;
-    }
-
-    /**
-     * 解析时间对象为Date
-     */
-    private Date parseDate(Object value) {
-        if (value instanceof Date) {
-            return (Date) value;
-        }
-        try {
-            return SDF.parse(value.toString());
-        } catch (ParseException e) {
-            throw new RuntimeException(I18nUtil.get("time.format.error") + value, e);
-        }
-    }
-
-    /**
-     * 内部类:表示时间范围(start <= create_time <= end)
-     */
-    private static class DateRange {
-        private final Date start;
-        private final Date end;
-
-        public DateRange(Date start, Date end) {
-            this.start = start;
-            this.end = end;
-        }
-
-        public Date getStart() {
-            return start;
-        }
-
-        public Date getEnd() {
-            return end;
-        }
-    }
-
-
-
-
-
 }

+ 3 - 2
mall-service/src/main/java/com/txz/mall/configurer/TableShardingAlgorithm.java

@@ -2,6 +2,7 @@ package com.txz.mall.configurer;
 
 import com.alibaba.fastjson.JSONObject;
 import com.txz.mall.util.I18nUtil;
+import com.txz.mall.util.OrderUtils;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
 
@@ -58,7 +59,7 @@ public class TableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comp
         if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
             for (Comparable<?> val : values.get("uid")) {
                 Long uid = (Long) val;
-                shardingKeys.add(uid % 10000);
+                shardingKeys.add(Long.parseLong(OrderUtils.getLastFourDigitsOfTheUserId(uid)));
             }
             return shardingKeys;
         }
@@ -92,7 +93,7 @@ public class TableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comp
         Collection<String> resultTables = new ArrayList<>();
         for (Long key : shardingKeys) {
             // 计算分区(和你原逻辑一致:key % 5)
-            long tableSuffix = key % 5;
+            long tableSuffix = (int) Math.floorMod(key, 5);
             // 匹配可用表(如m_store_pink_3)
             for (String targetTable : availableTargets) {
                 if (targetTable.endsWith(String.valueOf(tableSuffix))) {

+ 16 - 123
mall-service/src/main/java/com/txz/mall/configurer/UserSignDatabaseShardingAlgorithm.java

@@ -1,101 +1,31 @@
 package com.txz.mall.configurer;
 
+import com.txz.mall.util.OrderUtils;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
 
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
 
 public class UserSignDatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
 
-
-    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");
-
-    private static final Set<Integer> FIRST_HALF_MONTHS = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6));
-    private static final Set<Integer> SECOND_HALF_MONTHS = new HashSet<>(Arrays.asList(7, 8, 9, 10, 11, 12));
-
     @Override
     public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
         // 判断操作类型
-     //   boolean isInsert = isInsertOperation(shardingValue);
-
-        // 提取分片键
-        Date createTime = getCreateTime(shardingValue);
         Long userId = getUserId(shardingValue);
-
-
-
-        // 插入操作必须包含create_time和user_id
-     //   if (isInsert && (createTime == null || userId == null)) {
-          //  throw new IllegalArgumentException("插入数据必须包含create_time和user_id");
-     //   }
-
-        // 1-6月数据处理(维持原逻辑)
-        if (createTime != null && isFirstHalfYear(createTime)) {
-            return routeFirstHalf(availableTargets, userId);
-        }
-
-        // 7-12月数据处理
-        if (createTime != null && isSecondHalfYear(createTime)) {
-            return routeSecondHalf(availableTargets, userId);
+        // 2. 每个分表键对应一个表,收集所有匹配的表
+        Collection<String> resultTables = new ArrayList<>();
+        // 计算分区(和你原逻辑一致:key % 5)
+        long tableSuffix = (int) Math.floorMod(userId, 4);
+        // 匹配可用表(如m_store_pink_3)
+        for (String targetTable : availableTargets) {
+          if (targetTable.endsWith(String.valueOf(tableSuffix))) {
+            resultTables.add(targetTable);
+            break; // 找到对应表就跳出,避免重复
+          }
         }
-
-        // 查询时无create_time:扫描所有符合条件的库
-        return filterAllDatabases(availableTargets, userId);
-    }
-
-    // 1-6月路由逻辑(维持原逻辑:mall_0/mall_1)
-    private Collection<String> routeFirstHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-           // String lastFour = getLastFourDigits(userId);
-            long dbIndex = userId % 2; // 0→mall_0,1→mall_1
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        // 查询时无user_id:扫描1-6月的库
-        return Arrays.asList("ds0", "ds1");
-    }
-
-    // 7-12月路由逻辑(mall_1/mall_2)
-    private Collection<String> routeSecondHalf(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            //String lastFour = getLastFourDigits(userId);
-            long dbIndex = 2 + (userId % 2); // 1→mall_1,2→mall_2
-            String targetDb = "ds" + dbIndex;
-            if (availableTargets.contains(targetDb)) {
-                return Collections.singleton(targetDb);
-            }
-        }
-        // 查询时无user_id:扫描7-12月的库
-        return Arrays.asList("ds2", "ds3");
-    }
-
-    // 判断是否为插入操作
-    private boolean isInsertOperation(ComplexKeysShardingValue<?> shardingValue) {
-        //return shardingValue.getSqlType() != null && shardingValue.getSqlType().name().startsWith("INSERT");
-
-        //shardingValue
-        return true;
-    }
-
-    // 提取并解析create_time
-    private Date getCreateTime(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
-        if (values.containsKey("create_day") && !values.get("create_day").isEmpty()) {
-            Object value = values.get("create_day").iterator().next();
-            if (value instanceof Date) return (Date) value;
-            try {
-                return SDF.parse(value.toString());
-            } catch (ParseException e) {
-                throw new RuntimeException("UserSignDatabaseShardingAlgorithm create_day格式错误,应为yyyy-MM-dd");
-            }
-        }
-
-
-        return null;
+        return availableTargets;
     }
 
     // 提取user_id
@@ -103,46 +33,9 @@ public class UserSignDatabaseShardingAlgorithm implements ComplexKeysShardingAlg
         Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
         if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
             Long uid = (Long) values.get("uid").iterator().next();
-            return uid % 10000;
+            return Long.parseLong(OrderUtils.getLastFourDigitsOfTheUserId(uid));
         }
-
-
         return null;
     }
 
-    // 判断是否为1-6月
-    private boolean isFirstHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return FIRST_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    // 判断是否为7-12月
-    private boolean isSecondHalfYear(Date date) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(date);
-        return SECOND_HALF_MONTHS.contains(calendar.get(Calendar.MONTH) + 1);
-    }
-
-    // 获取user_id后四位
-    private String getLastFourDigits(String value) {
-        if (value == null || value.isEmpty()) return "0";
-        return value.substring(Math.max(0, value.length() - 4));
-    }
-
-    // 无create_time时的全量库过滤
-    private Collection<String> filterAllDatabases(Collection<String> availableTargets, Long userId) {
-        if (userId != null) {
-            // 有user_id但无时间时,需扫描所有可能的库(mall_0/mall_1/mall_2)
-            return Arrays.asList("ds0", "ds1", "ds2","ds3");
-        }
-        // 无任何条件时扫描所有库
-        return availableTargets;
-    }
-
-
-
-
-
-
 }

+ 2 - 1
mall-service/src/main/java/com/txz/mall/configurer/UserSignTableShardingAlgorithm.java

@@ -1,6 +1,7 @@
 package com.txz.mall.configurer;
 
 import com.txz.mall.util.I18nUtil;
+import com.txz.mall.util.OrderUtils;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
 
@@ -23,7 +24,7 @@ public class UserSignTableShardingAlgorithm implements ComplexKeysShardingAlgori
         Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
         if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
             Long uid = (Long) values.get("uid").iterator().next();
-            return uid % 10000;
+            return Long.parseLong(OrderUtils.getLastFourDigitsOfTheUserId(uid));
         }
 
         return null;

+ 41 - 41
mall-service/src/main/java/com/txz/mall/controller/appcontroller/AppOrderController.java

@@ -37,31 +37,31 @@ import java.util.List;
 @RestController
 @RequestMapping("/app/order")
 public class AppOrderController {
-    
+
     private static Logger log = LoggerFactory.getLogger(AppOrderController.class);
-    
+
     @Resource
     private StoreOrderService storeOrderService;
     @Resource
     private OrderServiceBusiness orderServiceBusiness;
-    
+
     @Resource
     private CifUserDubboServiceClient userDubboServiceClient;
-    
+
     @PostMapping("/add")
     @ApiOperation(value = "创建订单")
     public Result add(@Validated @RequestBody CreateOrderRequest orderRequest) {
-        
-        
+
+
         if (orderRequest == null) {
             return Result.fail(ResultCode.OBJECT_IS_NULL);
         }
         Long tokenUserId = AuthService.getTokenUserId(null);
-        UserDTO user = userDubboServiceClient.getUser(tokenUserId);
-        if (user.getHasOrder() != 1) {
-            return Result.fail(ResultCode.USER_STATUS_IS_ERROR);
-        }
-        
+//        UserDTO user = userDubboServiceClient.getUser(tokenUserId);
+//        if (user.getHasOrder() != 1) {
+//            return Result.fail(ResultCode.USER_STATUS_IS_ERROR);
+//        }
+
         orderRequest.setUserId(tokenUserId);
         MyRecord record = storeOrderService.createOrder(orderRequest);
         return Result.success(record);
@@ -116,13 +116,13 @@ public class AppOrderController {
     @PutMapping("/binding/address")
     @ApiOperation(value = "订单绑定地址")
     public Result update(@RequestBody StoreOrderUpdateParam storeOrderUpdateParam) {
-        
+
         try {
             StoreOrder storeOrder = new StoreOrder();
             storeOrder.setOrderId(storeOrderUpdateParam.getOrderId());
             storeOrder.setAddressId(storeOrderUpdateParam.getAddressId());
             EasyToUseUtil.appUpdateAssignment(new Date(), storeOrder);
-            
+
             storeOrderService.bindingAddress(storeOrder);
         } catch (Exception e) {
             log.error("更新对象操作异常e:{}", e);
@@ -130,8 +130,8 @@ public class AppOrderController {
         }
         return Result.success();
     }
-    
-    
+
+
     //    @GetMapping("/detail")
     //    @ApiOperation(value = "订单获取详情")
     //    public Result<StoreOrderVO> detail(@RequestParam Long id) {
@@ -141,20 +141,20 @@ public class AppOrderController {
     //        StoreOrderVO vo = orderServiceBusiness.orderDetail(id,null);
     //        return Result.success(vo);
     //    }
-    
+
     @GetMapping("/detail")
     @ApiOperation(value = "订单获取详情")
     public Result<StoreOrderVO> detail(@RequestParam(value = "id", required = false) Long id
             , @RequestParam(value = "orderNo", required = false) String orderNo) {
-        
+
         if (ObjectUtils.isEmpty(orderNo)) {
             return Result.fail(ResultCode.CODE_IS_NULL);
         }
         StoreOrderVO vo = orderServiceBusiness.orderDetail(id, orderNo);
         return Result.success(vo);
     }
-    
-    
+
+
     @PostMapping("/list")
     @ApiOperation(value = "订单获取列表")
     public Result<List<StoreOrderVO>> list(@RequestBody StoreOrderDTO dto) {
@@ -165,11 +165,11 @@ public class AppOrderController {
             return Result.fail(ResultCode.INTERNAL_SERVER_ERROR);
         }
     }
-    
+
     @PostMapping("/app/list")
     @ApiOperation(value = "订单获取列表")
     public Result<List<StoreOrderVO>> appList(@RequestBody StoreOrderAppDTO dto) {
-        
+
         Long tokenUserId = AuthService.getTokenUserId(null);
         dto.setUserId(tokenUserId);
         PageHelper.startPage(dto.getPage(), dto.getSize());
@@ -183,13 +183,13 @@ public class AppOrderController {
         }
         return Result.success(pageInfo);
     }
-    
+
     @ApiOperation(value = "获取订单各状态数量")
     @GetMapping(value = "/status/num")
     public Result<StoreOrderCountItemVO> getOrderStatusNum() {
         return Result.success(storeOrderService.getOrderStatusNum());
     }
-    
+
     //    @ApiOperation("导出订单")
     //    @PostMapping("/export")
     //    public Result exportFile(@RequestBody StoreOrderDTO dto, HttpServletResponse response) {
@@ -203,7 +203,7 @@ public class AppOrderController {
     //        storeOrderService.refund(id);
     //        return Result.success();
     //    }
-    
+
     @ApiOperation("关闭订单")
     @PostMapping("/close")
     public Result close(@RequestParam("orderNo") String orderNo) {
@@ -213,7 +213,7 @@ public class AppOrderController {
         storeOrderService.close(orderNo);
         return Result.success();
     }
-    
+
     @ApiOperation("取消订单")
     @PostMapping("/cancel")
     public Result cancel(@RequestParam("orderNo") String orderNo) {
@@ -223,79 +223,79 @@ public class AppOrderController {
         storeOrderService.cancel(orderNo);
         return Result.success();
     }
-    
+
     @ApiOperation("联系用户")
     @PostMapping("/contactUser")
     public Result contactUser(@RequestParam("userId") Long userId) {
         //        storeOrderService.contactUser(userId);
         return Result.success();
     }
-    
+
     //    @ApiOperation("批量发货")
     //    @PostMapping("/batchDelivery")
     //    public Result batchDelivery(@RequestBody List<StoreOrderDeliveryDTO> list) {
     //        storeOrderService.batchDelivery(list);
     //        return Result.success();
     //    }
-    
+
     @ApiOperation(value = "预下单")
     @PostMapping(value = "/pre/order")
     public Result preOrder(@RequestBody @Validated PreOrderRequest request) {
         Long tokenUserId = AuthService.getTokenUserId(null);
         request.setUserId(tokenUserId);
         return Result.success(storeOrderService.preOrder(request));
-        
+
     }
-    
+
     @ApiOperation(value = "加载预下单")
     @PostMapping(value = "load/pre")
     public Result<PreOrderResponse> loadPreOrder(@RequestParam String preOrderNo) {
         if (ObjectUtils.isEmpty(preOrderNo)) {
             return Result.fail(ResultCode.CODE_IS_NULL);
         }
-        
+
         Long tokenUserId = AuthService.getTokenUserId(null);
         return Result.success(storeOrderService.loadPreOrder(preOrderNo));
     }
-    
+
     @ApiOperation(value = "计算订单价格")
     @PostMapping(value = "/computed/price")
     public Result<ComputedOrderPriceResponse> computedPrice(@Validated @RequestBody OrderComputedPriceRequest request) {
-        
+
         Long tokenUserId = AuthService.getTokenUserId(null);
         request.setUserId(tokenUserId);
         return Result.success(storeOrderService.computedOrderPrice(request));
     }
-    
+
     @ApiOperation(value = "去支付")
     @PostMapping(value = "/goPay")
     public Result getPayResult(@RequestBody GoPinkDTO dto) {
-        
+
         Long tokenUserId = AuthService.getTokenUserId(null);
         dto.setUserId(tokenUserId);
         return storeOrderService.goPay(dto);
     }
-    
+
     //    @ApiOperation("导出发货单")
     //    @PostMapping("/exportDelivery")
     //    public Result exportDelivery(HttpServletResponse response) {
     //        storeOrderService.exportDelivery(response);
     //        return Result.success();
     //    }
-    
+
     //    @ApiOperation("导入发货单")
     //    @PostMapping("/importDelivery")
     //    public Result importDelivery(@JSONField(serialize = false) @RequestParam("file") MultipartFile file) {
     //        storeOrderService.importDelivery(file);
     //        return Result.success();
     //    }
-    
-    
+
+
     @ApiOperation("待处理红点数")
     @GetMapping("/pendingRedDots")
     public Result pendingRedDots() {
         return Result.success(storeOrderService.pendingRedDots());
     }
-    
-    
+
+
 }

+ 5 - 0
mall-service/src/main/java/com/txz/mall/core/AbstractService.java

@@ -48,6 +48,11 @@ public abstract class AbstractService<T> implements Service<T> {
         mapper.updateByPrimaryKeySelective(model);
     }
 
+    @Override
+    public void update(T model,Object var2) {
+      mapper.updateByConditionSelective(model,var2);
+    }
+
     @Override
     public T findById(Number id) {
         return mapper.selectByPrimaryKey(id);

+ 1 - 0
mall-service/src/main/java/com/txz/mall/core/Service.java

@@ -14,6 +14,7 @@ public interface Service<T> {
     void deleteById(Number id);//通过主鍵刪除
     void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”
     void update(T model);//更新
+    void update(T model,Object var2);//更新
     T findById(Number id);//通过ID查找
     T findBy(String fieldName, Object value) throws TooManyResultsException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束
     List<T> findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”

+ 9 - 0
mall-service/src/main/java/com/txz/mall/dao/OrderIndexMapper.java

@@ -0,0 +1,9 @@
+package com.txz.mall.dao;
+
+import com.txz.mall.core.Mapper;
+import com.txz.mall.model.OrderIndex;
+
+public interface OrderIndexMapper extends Mapper<OrderIndex> {
+}
+
+

+ 67 - 0
mall-service/src/main/java/com/txz/mall/model/OrderIndex.java

@@ -0,0 +1,67 @@
+package com.txz.mall.model;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.*;
+import java.util.Date;
+
+@Data
+@Table(name = "m_order_index")
+public class OrderIndex {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "order_id")
+    @ApiModelProperty("订单号")
+    private String orderId;
+    @Column(name = "real_name")
+    @ApiModelProperty(value = "用户姓名")
+    private String realName;
+    @Column(name = "user_phone")
+    @ApiModelProperty(value = "用户电话")
+    private String userPhone;
+    @Column(name = "pay_num")
+    @ApiModelProperty("购买数量")
+    private Integer payNum;
+    @Column(name = "product_name")
+    @ApiModelProperty("商品名称")
+    private String productName;
+    @Column(name = "image")
+    @ApiModelProperty("商品图片")
+    private String image;
+    @Column(name = "sku")
+    @ApiModelProperty("商品sku")
+    private String sku;
+    @ApiModelProperty(value = "订单状态(0:待发货;1:待收货;3:已完成; 4:已关闭  5:已取消)")
+    private Integer status;
+    @ApiModelProperty(value = "状态 1进行中 2已完成 3未完成")
+    @Column(name = "store_pink_status")
+    private Integer storePinkStatus;
+    @Column(name = "uid")
+    @ApiModelProperty("用户ID")
+    private Long uid;
+    @ApiModelProperty(value = "快递单号/手机号")
+    @Column(name = "delivery_id")
+    private String deliveryId;
+    @ApiModelProperty(value = "快递名称/送货人姓名")
+    @Column(name = "delivery_name")
+    private String deliveryName;
+    @Column(name = "db_index")
+    @ApiModelProperty("库位索引 ds0..ds3 对应的数字 0..3")
+    private Integer dbIndex;
+    @Column(name = "table_suffix")
+    @ApiModelProperty("分表后缀 0..14")
+    private Integer tableSuffix;
+    @Column(name = "create_time")
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+    @Column(name = "pay_time")
+    @ApiModelProperty(value = "支付时间")
+    private Date payTime;
+    @Column(name = "yyyy_mm")
+    @ApiModelProperty("形如 202501 的月份标识,便于归档与查询")
+    private Integer yyyyMm;
+}
+
+

+ 12 - 0
mall-service/src/main/java/com/txz/mall/service/OrderIndexService.java

@@ -0,0 +1,12 @@
+package com.txz.mall.service;
+
+import com.txz.mall.core.Service;
+import com.txz.mall.model.OrderIndex;
+
+
+/**
+ * Created by CodeGenerator on 2025/08/05.
+ */
+public interface OrderIndexService extends Service<OrderIndex> {
+
+}

+ 16 - 0
mall-service/src/main/java/com/txz/mall/service/impl/OrderIndexServiceImpl.java

@@ -0,0 +1,16 @@
+package com.txz.mall.service.impl;
+
+import com.txz.mall.core.AbstractService;
+import com.txz.mall.model.OrderIndex;
+import com.txz.mall.service.OrderIndexService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+
+/**
+ * Created by CodeGenerator on 2025/08/05.
+ */
+@Service
+@Transactional
+public class OrderIndexServiceImpl extends AbstractService<OrderIndex> implements OrderIndexService {
+}

Fichier diff supprimé car celui-ci est trop grand
+ 452 - 395
mall-service/src/main/java/com/txz/mall/service/impl/StoreOrderServiceImpl.java


+ 15 - 1
mall-service/src/main/java/com/txz/mall/util/OrderUtils.java

@@ -1,5 +1,7 @@
 package com.txz.mall.util;
 
+import org.apache.commons.lang3.StringUtils;
+
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -74,7 +76,7 @@ public class OrderUtils {
      * 生成时间戳
      */
     public static String getDateTime() {
-        DateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
+        DateFormat sdf = new SimpleDateFormat("yyMMdd");
         return sdf.format(new Date());
     }
 
@@ -128,6 +130,18 @@ public class OrderUtils {
         return ORDER_CODE + format;
     }
 
+  /**
+   * 获取用户ID的分库分表标识(用于订单号生成)
+   * 直接取模,避免哈希导致的不均匀分布
+   */
+  public static String getLastFourDigitsOfTheUserId(Long userId) {
+    if (userId == null) {
+      return "0000";
+    }
+    long mod = Math.floorMod(userId, 10000);
+    return String.format("%04d", mod);
+  }
+
 
     public static String getPreOrderCode() {
 

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff