Эх сурвалжийг харах

分库分表算法全局替换

yubin 3 долоо хоног өмнө
parent
commit
5a810736fb

+ 81 - 0
mall-service/src/main/java/com/txz/mall/configurer/DatabaseShardingAlgorithmForInTest.java

@@ -0,0 +1,81 @@
+package com.txz.mall.configurer;
+
+import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
+import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.text.ParseException;
+public class DatabaseShardingAlgorithmForInTest implements ComplexKeysShardingAlgorithm<Comparable<?>> {
+
+
+    // 订单ID格式:BH + 6位年月日(如251022=20251022) + ... + 最后4位为用户ID后4位
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");
+
+    @Override
+    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+        // 只处理 order_id IN 条件
+        List<String> orderIds = getOrderIds(shardingValue);
+        if (orderIds.isEmpty()) {
+            throw new IllegalArgumentException("仅支持 order_id IN 查询");
+        }
+
+        // 按 order_id 顺序生成库列表(与 IN 条件顺序一致)
+        List<String> targetDbs = new ArrayList<>(orderIds.size());
+        for (String orderId : orderIds) {
+            // 解析月份(判断1-6月/7-12月)
+            int month = getMonthFromOrderId(orderId);
+            // 解析用户ID后4位(用于%2)
+            long userIdLast4 = getUserIdLast4FromOrderId(orderId);
+            // 计算库索引
+            String db = calculateDb(month, userIdLast4);
+            targetDbs.add(db);
+        }
+        return targetDbs;
+    }
+
+    // 提取 IN 条件中的 order_id 列表(保持原始顺序)
+    private List<String> getOrderIds(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+        Collection<Comparable<?>> values = shardingValue.getColumnNameAndShardingValuesMap().get("order_id");
+        List<String> result = new ArrayList<>();
+        if (values != null) {
+            for (Comparable<?> val : values) {
+                result.add(val.toString());
+            }
+        }
+        return result;
+    }
+
+    // 从订单ID提取月份(如 BH251022xxx → 10月)
+    private int getMonthFromOrderId(String orderId) {
+        try {
+            String dateStr = "20" + orderId.substring(2, 8); // 取第2-8位(251022→20251022)
+            Date date = DATE_FORMAT.parse(dateStr);
+            return date.getMonth() + 1; // 月份0-11,+1转为1-12
+        } catch (ParseException | StringIndexOutOfBoundsException e) {
+            throw new RuntimeException("订单ID格式错误:" + orderId, e);
+        }
+    }
+
+    // 从订单ID提取最后4位作为用户ID后4位
+    private long getUserIdLast4FromOrderId(String orderId) {
+        try {
+            return Long.parseLong(orderId.substring(orderId.length() - 4));
+        } catch (StringIndexOutOfBoundsException | NumberFormatException e) {
+            throw new RuntimeException("订单ID格式错误:" + orderId, e);
+        }
+    }
+
+    // 计算库名:1-6月→ds0/ds1;7-12月→ds2/ds3(用户ID后4位%2)
+    private String calculateDb(int month, long userIdLast4) {
+        if (month >= 1 && month <= 6) {
+            return "ds" + (userIdLast4 % 2);
+        } else {
+            return "ds" + (2 + (userIdLast4 % 2));
+        }
+    }
+
+}

+ 379 - 89
mall-service/src/main/java/com/txz/mall/configurer/StoreOrderInfoDatabaseShardingAlgorithm.java

@@ -2,6 +2,7 @@ package com.txz.mall.configurer;
 
 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;
@@ -9,157 +10,446 @@ import java.util.*;
 
 public class StoreOrderInfoDatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
 
-
-    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-    private static final SimpleDateFormat SDFORDERNO = new SimpleDateFormat("yyyyMMdd");
+//
+//    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//    private static final SimpleDateFormat SDFORDERNO = 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) {
+//        // 判断操作类型
+//        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);
+//        }
+//
+//        // 查询时无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_time") && !values.get("create_time").isEmpty()) {
+////            Object value = values.get("create_time").iterator().next();
+////            if (value instanceof Date) return (Date) value;
+////            try {
+////                return SDF.parse(value.toString());
+////            } catch (ParseException e) {
+////                throw new RuntimeException("create_time格式错误,应为yyyy-MM-dd HH:mm:ss");
+////            }
+////        }
+//
+//
+//        if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
+//            String  orderId = (String) values.get("order_no").iterator().next();
+//            // 提取日期位并转换为Date类型
+//            String dateStr = "20"+orderId.substring(2, 8);
+//            try {
+//                return SDFORDERNO.parse(dateStr);
+//            } catch (ParseException e) {
+//                throw new RuntimeException("StoreOrderInfoDatabaseShardingAlgorithm从订单号中提取日期错误"+dateStr);
+//            }
+//
+//        }
+//
+//
+//        return null;
+//    }
+//
+//    // 提取user_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;
+////        }
+//
+//        if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
+//            String  orderId = (String) values.get("order_no").iterator().next();
+//            // 提取后4位并转换为long类型
+//            String lastFourStr = orderId.substring(orderId.length() - 4);
+//            return Long.parseLong(lastFourStr);
+//        }
+//
+//
+//        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;
+//    }
+//
+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) {
-        // 判断操作类型
-        boolean isInsert = isInsertOperation(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);
+    }
 
-        // 提取分片键
-        Date createTime = getCreateTime(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_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) {
+                    throw new RuntimeException("解析order_no分库条件失败: " + orderId, e);
+                }
+            }
+        }
+        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和user_id
-        if (isInsert && (createTime == null || userId == null)) {
-          //  throw new IllegalArgumentException("插入数据必须包含create_time和user_id");
+    /**
+     * 提取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);
+            }
         }
 
-        // 1-6月数据处理(维持原逻辑)
-        if (createTime != null && isFirstHalfYear(createTime)) {
-            return routeFirstHalf(availableTargets, userId);
+
+        // 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;
+            }
         }
 
-        // 7-12月数据处理
-        if (createTime != null && isSecondHalfYear(createTime)) {
-            return routeSecondHalf(availableTargets, userId);
+        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;
+    }
 
-        // 查询时无create_time:扫描所有符合条件的库
-        return filterAllDatabases(availableTargets, userId);
+    /**
+     * 根据时间和用户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月路由逻辑(维持原逻辑:mall_0/mall_1)
+    /**
+     * 1-6月路由(ds0/ds1)
+     */
     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
+            long dbIndex = userId % 2;
             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)
+    /**
+     * 7-12月路由(ds2/ds3)
+     */
     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
+            long dbIndex = 2 + (userId % 2); // 2或3
             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_time") && !values.get("create_time").isEmpty()) {
-//            Object value = values.get("create_time").iterator().next();
-//            if (value instanceof Date) return (Date) value;
-//            try {
-//                return SDF.parse(value.toString());
-//            } catch (ParseException e) {
-//                throw new RuntimeException("create_time格式错误,应为yyyy-MM-dd HH:mm:ss");
-//            }
-//        }
-
-
-        if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
-            String  orderId = (String) values.get("order_no").iterator().next();
-            // 提取日期位并转换为Date类型
-            String dateStr = "20"+orderId.substring(2, 8);
-            try {
-                return SDFORDERNO.parse(dateStr);
-            } catch (ParseException e) {
-                throw new RuntimeException("StoreOrderInfoDatabaseShardingAlgorithm从订单号中提取日期错误"+dateStr);
-            }
-
-        }
-
-
-        return null;
-    }
-
-    // 提取user_id
+    /**
+     * 提取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;
-//        }
-
-        if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
-            String  orderId = (String) values.get("order_no").iterator().next();
-            // 提取后4位并转换为long类型
-            String lastFourStr = orderId.substring(orderId.length() - 4);
-            return Long.parseLong(lastFourStr);
+        if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
+            Long uid = (Long) values.get("uid").iterator().next();
+            return uid % 10000;
         }
-
-
         return null;
     }
 
-    // 判断是否为1-6月
+    /**
+     * 判断是否为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月
+    /**
+     * 判断是否为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 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("时间格式错误: " + 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;
+        }
+    }
 
 
 

+ 81 - 28
mall-service/src/main/java/com/txz/mall/configurer/StoreOrderInfoTableShardingAlgorithm.java

@@ -3,49 +3,102 @@ package com.txz.mall.configurer;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 public class StoreOrderInfoTableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
 
-    @Override
-    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Long userId = getUserId(shardingValue);
-        // 查询时无create_time:扫描所有符合条件的库
-        return filterAllTable(availableTargets, userId);
-    }
+//    @Override
+//    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+//        Long userId = getUserId(shardingValue);
+//        // 查询时无create_time:扫描所有符合条件的库
+//        return filterAllTable(availableTargets, userId);
+//    }
+//
+//
+//    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;
+////        }
+//
+//        if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
+//            String  orderId = (String) values.get("order_no").iterator().next();
+//            // 提取后4位并转换为long类型
+//            String lastFourStr = orderId.substring(orderId.length() - 4);
+//            return Long.parseLong(lastFourStr);
+//        }
+//
+//        return null;
+//    }
+//
+//    private Collection<String> filterAllTable(Collection<String> availableTargets, Long userId) {
+//        //这个模树要拎出去形成配置项
+//        long mod = userId % 5;
+//        for (String tableName : availableTargets) {
+//            if (tableName.endsWith(String.valueOf(mod))) {
+//                List<String> list = Arrays.asList(tableName);
+//                return list;
+//            }
+//        }
+//        throw new IllegalArgumentException("未找到匹配的表: " + availableTargets + ", 分片值: " + userId);
+//
+//    }
 
 
-    private Long getUserId(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+
+    // 步骤1:修改getUserId,返回所有order_id对应的分表键(后4位)
+    private Collection<Long> getShardingKeys(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;
-//        }
+        Collection<Long> shardingKeys = new ArrayList<>();
+
+
 
+        // 核心:处理order_id的IN条件,遍历所有order_id
         if (values.containsKey("order_no") && !values.get("order_no").isEmpty()) {
-            String  orderId = (String) values.get("order_no").iterator().next();
-            // 提取后4位并转换为long类型
-            String lastFourStr = orderId.substring(orderId.length() - 4);
-            return Long.parseLong(lastFourStr);
+            for (Comparable<?> val : values.get("order_no")) {
+                String orderId = (String) val;
+                // 提取每个order_id的后4位,作为分表键
+                String lastFourStr = orderId.substring(orderId.length() - 4);
+                shardingKeys.add(Long.parseLong(lastFourStr));
+            }
+            return shardingKeys;
         }
 
-        return null;
+        return shardingKeys;
     }
 
-    private Collection<String> filterAllTable(Collection<String> availableTargets, Long userId) {
-        //这个模树要拎出去形成配置项
-        long mod = userId % 5;
-        for (String tableName : availableTargets) {
-            if (tableName.endsWith(String.valueOf(mod))) {
-                List<String> list = Arrays.asList(tableName);
-                return list;
+    // 步骤2:修改doSharding,返回所有匹配的表
+    @Override
+    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+        // String logicTableName = shardingValue.getLogicTableName();
+
+        // 1. 获取所有分表键(每个order_id对应一个)
+        Collection<Long> shardingKeys = getShardingKeys(shardingValue);
+        if (shardingKeys.isEmpty()) {
+            throw new IllegalArgumentException("分表键不能为空(需uid或order_id)");
+        }
+
+        // 2. 每个分表键对应一个表,收集所有匹配的表
+        Collection<String> resultTables = new ArrayList<>();
+        for (Long key : shardingKeys) {
+            // 计算分区(和你原逻辑一致:key % 5)
+            long tableSuffix = key % 5;
+            // 匹配可用表(如m_store_pink_3)
+            for (String targetTable : availableTargets) {
+                if (targetTable.endsWith(String.valueOf(tableSuffix))) {
+                    resultTables.add(targetTable);
+                    break; // 找到对应表就跳出,避免重复
+                }
             }
         }
-        throw new IllegalArgumentException("未找到匹配的表: " + availableTargets + ", 分片值: " + userId);
 
+        // 3. 若没有匹配的表,抛出异常
+        if (resultTables.isEmpty()) {
+            throw new IllegalArgumentException("未找到匹配的表: " + availableTargets + ", 分表键: " + shardingKeys);
+        }
+
+        return resultTables;
     }
 
 }

+ 378 - 87
mall-service/src/main/java/com/txz/mall/configurer/StoreOrderStatusDatabaseShardingAlgorithm.java

@@ -2,6 +2,7 @@ package com.txz.mall.configurer;
 
 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;
@@ -10,156 +11,446 @@ import java.util.*;
 public class StoreOrderStatusDatabaseShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
 
 
+//    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//    private static final SimpleDateFormat SDFORDERNO = 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) {
+//        // 判断操作类型
+//        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);
+//        }
+//
+//        // 查询时无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_time") && !values.get("create_time").isEmpty()) {
+////            Object value = values.get("create_time").iterator().next();
+////            if (value instanceof Date) return (Date) value;
+////            try {
+////                return SDF.parse(value.toString());
+////            } catch (ParseException e) {
+////                throw new RuntimeException("create_time格式错误,应为yyyy-MM-dd HH:mm:ss");
+////            }
+////        }
+//
+//
+//        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
+//            String  orderId = (String) values.get("order_id").iterator().next();
+//            // 提取日期位并转换为Date类型
+//            String dateStr = "20"+orderId.substring(2, 8);
+//            try {
+//                return SDFORDERNO.parse(dateStr);
+//            } catch (ParseException e) {
+//                throw new RuntimeException("StoreOrderStatusDatabaseShardingAlgorithm从订单号中提取日期错误"+dateStr);
+//            }
+//
+//        }
+//
+//
+//        return null;
+//    }
+//
+//    // 提取user_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;
+////        }
+//
+//        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
+//            String  orderId = (String) values.get("order_id").iterator().next();
+//            // 提取后4位并转换为long类型
+//            String lastFourStr = orderId.substring(orderId.length() - 4);
+//            return Long.parseLong(lastFourStr);
+//        }
+//
+//
+//        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;
+//    }
+
+
     private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-    private static final SimpleDateFormat SDFORDERNO = new SimpleDateFormat("yyyyMMdd");
+    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) {
-        // 判断操作类型
-        boolean isInsert = isInsertOperation(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;
+        }
 
-        // 提取分片键
-        Date createTime = getCreateTime(shardingValue);
+        // 处理无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("解析order_id分库条件失败: " + orderId, e);
+                }
+            }
+        }
+        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和user_id
-        if (isInsert && (createTime == null || userId == null)) {
-          //  throw new IllegalArgumentException("插入数据必须包含create_time和user_id");
+    /**
+     * 提取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);
+            }
         }
 
-        // 1-6月数据处理(维持原逻辑)
-        if (createTime != null && isFirstHalfYear(createTime)) {
-            return routeFirstHalf(availableTargets, userId);
+
+        // 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;
+            }
         }
 
-        // 7-12月数据处理
-        if (createTime != null && isSecondHalfYear(createTime)) {
-            return routeSecondHalf(availableTargets, userId);
+        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;
+    }
 
-        // 查询时无create_time:扫描所有符合条件的库
-        return filterAllDatabases(availableTargets, userId);
+    /**
+     * 根据时间和用户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月路由逻辑(维持原逻辑:mall_0/mall_1)
+    /**
+     * 1-6月路由(ds0/ds1)
+     */
     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
+            long dbIndex = userId % 2;
             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)
+    /**
+     * 7-12月路由(ds2/ds3)
+     */
     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
+            long dbIndex = 2 + (userId % 2); // 2或3
             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_time") && !values.get("create_time").isEmpty()) {
-//            Object value = values.get("create_time").iterator().next();
-//            if (value instanceof Date) return (Date) value;
-//            try {
-//                return SDF.parse(value.toString());
-//            } catch (ParseException e) {
-//                throw new RuntimeException("create_time格式错误,应为yyyy-MM-dd HH:mm:ss");
-//            }
-//        }
-
-
-        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
-            String  orderId = (String) values.get("order_id").iterator().next();
-            // 提取日期位并转换为Date类型
-            String dateStr = "20"+orderId.substring(2, 8);
-            try {
-                return SDFORDERNO.parse(dateStr);
-            } catch (ParseException e) {
-                throw new RuntimeException("StoreOrderStatusDatabaseShardingAlgorithm从订单号中提取日期错误"+dateStr);
-            }
-
-        }
-
-
-        return null;
-    }
-
-    // 提取user_id
+    /**
+     * 提取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;
-//        }
-
-        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
-            String  orderId = (String) values.get("order_id").iterator().next();
-            // 提取后4位并转换为long类型
-            String lastFourStr = orderId.substring(orderId.length() - 4);
-            return Long.parseLong(lastFourStr);
+        if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
+            Long uid = (Long) values.get("uid").iterator().next();
+            return uid % 10000;
         }
-
-
         return null;
     }
 
-    // 判断是否为1-6月
+    /**
+     * 判断是否为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月
+    /**
+     * 判断是否为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 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("时间格式错误: " + 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;
+        }
+    }
 
 
 

+ 86 - 30
mall-service/src/main/java/com/txz/mall/configurer/StoreOrderStatusTableShardingAlgorithm.java

@@ -3,49 +3,105 @@ package com.txz.mall.configurer;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
 import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 public class StoreOrderStatusTableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Comparable<?>> {
 
-    @Override
-    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
-        Long userId = getUserId(shardingValue);
-        // 查询时无create_time:扫描所有符合条件的库
-        return filterAllTable(availableTargets, userId);
-    }
-
+//    @Override
+//    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+//        Long userId = getUserId(shardingValue);
+//        // 查询时无create_time:扫描所有符合条件的库
+//        return filterAllTable(availableTargets, userId);
+//    }
+//
+//
+//    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;
+////        }
+//
+//        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
+//            String  orderId = (String) values.get("order_id").iterator().next();
+//            // 提取后4位并转换为long类型
+//            String lastFourStr = orderId.substring(orderId.length() - 4);
+//            return Long.parseLong(lastFourStr);
+//        }
+//
+//        return null;
+//    }
+//
+//    private Collection<String> filterAllTable(Collection<String> availableTargets, Long userId) {
+//        //这个模树要拎出去形成配置项
+//        long mod = userId % 5;
+//        for (String tableName : availableTargets) {
+//            if (tableName.endsWith(String.valueOf(mod))) {
+//                List<String> list = Arrays.asList(tableName);
+//                return list;
+//            }
+//        }
+//        throw new IllegalArgumentException("未找到匹配的表: " + availableTargets + ", 分片值: " + userId);
+//
+//    }
+private Collection<Long> getShardingKeys(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+    Map<String, Collection<Comparable<?>>> values = shardingValue.getColumnNameAndShardingValuesMap();
+    Collection<Long> shardingKeys = new ArrayList<>();
 
-    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;
+    // 优先处理uid(如果有)
+//    if (values.containsKey("uid") && !values.get("uid").isEmpty()) {
+//        for (Comparable<?> val : values.get("uid")) {
+//            Long uid = (Long) val;
+//            shardingKeys.add(uid % 10000);
 //        }
+//        return shardingKeys;
+//    }
 
-        if (values.containsKey("order_id") && !values.get("order_id").isEmpty()) {
-            String  orderId = (String) values.get("order_id").iterator().next();
-            // 提取后4位并转换为long类型
+    // 核心:处理order_id的IN条件,遍历所有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);
-            return Long.parseLong(lastFourStr);
+            shardingKeys.add(Long.parseLong(lastFourStr));
         }
-
-        return null;
+        return shardingKeys;
     }
 
-    private Collection<String> filterAllTable(Collection<String> availableTargets, Long userId) {
-        //这个模树要拎出去形成配置项
-        long mod = userId % 5;
-        for (String tableName : availableTargets) {
-            if (tableName.endsWith(String.valueOf(mod))) {
-                List<String> list = Arrays.asList(tableName);
-                return list;
+    return shardingKeys;
+}
+
+    // 步骤2:修改doSharding,返回所有匹配的表
+    @Override
+    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+        // String logicTableName = shardingValue.getLogicTableName();
+
+        // 1. 获取所有分表键(每个order_id对应一个)
+        Collection<Long> shardingKeys = getShardingKeys(shardingValue);
+        if (shardingKeys.isEmpty()) {
+            throw new IllegalArgumentException("分表键不能为空(需uid或order_id)");
+        }
+
+        // 2. 每个分表键对应一个表,收集所有匹配的表
+        Collection<String> resultTables = new ArrayList<>();
+        for (Long key : shardingKeys) {
+            // 计算分区(和你原逻辑一致:key % 5)
+            long tableSuffix = key % 5;
+            // 匹配可用表(如m_store_pink_3)
+            for (String targetTable : availableTargets) {
+                if (targetTable.endsWith(String.valueOf(tableSuffix))) {
+                    resultTables.add(targetTable);
+                    break; // 找到对应表就跳出,避免重复
+                }
             }
         }
-        throw new IllegalArgumentException("未找到匹配的表: " + availableTargets + ", 分片值: " + userId);
 
+        // 3. 若没有匹配的表,抛出异常
+        if (resultTables.isEmpty()) {
+            throw new IllegalArgumentException("未找到匹配的表: " + availableTargets + ", 分表键: " + shardingKeys);
+        }
+
+        return resultTables;
     }
 
 }

+ 66 - 0
mall-service/src/main/java/com/txz/mall/configurer/TableShardingAlgorithmForInTest.java

@@ -0,0 +1,66 @@
+package com.txz.mall.configurer;
+
+import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
+import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class TableShardingAlgorithmForInTest implements ComplexKeysShardingAlgorithm<Comparable<?>> {
+    private static final int TABLE_COUNT = 5; // 分5张表
+
+    @Override
+    public Collection<String> doSharding(Collection<String> availableTargets, ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+        // 只处理 order_id IN 条件
+        List<String> orderIds = getOrderIds(shardingValue);
+        if (orderIds.isEmpty()) {
+            throw new IllegalArgumentException("仅支持 order_id IN 查询");
+        }
+
+        // 按 order_id 顺序生成表列表(与分库结果顺序一致)
+        List<String> targetTables = new ArrayList<>(orderIds.size());
+        for (String orderId : orderIds) {
+            // 提取用户ID后4位(与分库算法逻辑一致)
+            long userIdLast4 = getUserIdLast4FromOrderId(orderId);
+            // 计算表索引(%5)
+            int tableIndex = (int) (userIdLast4 % TABLE_COUNT);
+            // 匹配实际表名(如逻辑表为t_order,实际表为t_order_0)
+            String targetTable = findTargetTable(availableTargets, tableIndex);
+            targetTables.add(targetTable);
+        }
+        return targetTables;
+    }
+
+    // 提取 IN 条件中的 order_id 列表(与分库顺序一致)
+    private List<String> getOrderIds(ComplexKeysShardingValue<Comparable<?>> shardingValue) {
+        Collection<Comparable<?>> values = shardingValue.getColumnNameAndShardingValuesMap().get("order_id");
+        List<String> result = new ArrayList<>();
+        if (values != null) {
+            for (Comparable<?> val : values) {
+                result.add(val.toString());
+            }
+        }
+        return result;
+    }
+
+    // 从订单ID提取最后4位(与分库算法完全一致)
+    private long getUserIdLast4FromOrderId(String orderId) {
+        try {
+            return Long.parseLong(orderId.substring(orderId.length() - 4));
+        } catch (StringIndexOutOfBoundsException | NumberFormatException e) {
+            throw new RuntimeException("订单ID格式错误:" + orderId, e);
+        }
+    }
+
+    // 找到对应索引的表(如索引3对应t_order_3)
+    private String findTargetTable(Collection<String> availableTargets, int tableIndex) {
+        String suffix = String.valueOf(tableIndex);
+        for (String table : availableTargets) {
+            if (table.endsWith(suffix)) {
+                return table;
+            }
+        }
+        throw new IllegalArgumentException("未找到表:" + availableTargets + ",索引:" + tableIndex);
+    }
+}