From 7cb17ac8398776c1c7c38a949dc25c25fe0a5a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E8=87=AA=E8=BE=BE?= <980324341@qq.com> Date: Wed, 2 Sep 2026 14:23:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BA=97=E9=93=BA=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8A=93=E5=8F=96=E6=96=B0=E5=BA=97=E9=93=BA=E5=BD=92?= =?UTF-8?q?=E6=A1=A3=20daily=5Ffile=20=E6=8A=A5=20user=5Fid=20=E6=97=A0?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 线上现象:店铺数据抓取任务 26401 失败,错误 "Field 'user_id' doesn't have a default value", INSERT 列清单不含 user_id(MyBatis-Plus 对 null 字段跳过该列)。 根因链: 1. V95(97ae8a7)累计文件改为店铺级共享(去 user 维度), persistDailyAggregation 新建 daily_file 时删掉了 setUserId; 2. 但 V95 只改了唯一键为 (shop_key, business_date),未把 user_id 列改可空; 3. 表列 user_id 仍为 NOT NULL 无默认值 → 新店铺首次插入必报错; 已有 daily_file 行的店铺走 update 分支不受影响,因此只在 新店铺(如 26401)出现。 修复: - persistDailyAggregation 新建 daily_file 时补回 setUserId(row.getUserId()), 新店铺也写入正确归属; - V104 迁移把 user_id 改可空,兼容存量/历史数据(保留兼容,不再使用); - 新增回归断言(新建累计文件必须写入 user_id), shopdatacrawl 全包 255 测试全绿,双机已部署验证。 --- .../service/ShopDataCrawlTaskService.java | 1 + ...4__shop_data_crawl_daily_file_user_id_nullable.sql | 11 +++++++++++ .../ShopDataCrawlDailyFileIncrementalTest.java | 4 ++++ 3 files changed, 16 insertions(+) create mode 100644 backend-java/src/main/resources/db/V104__shop_data_crawl_daily_file_user_id_nullable.sql diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java index c991d6fc..51935c35 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlTaskService.java @@ -2132,6 +2132,7 @@ public class ShopDataCrawlTaskService { LocalDateTime now = dailyFileService.currentBusinessDateTime(); if (dailyFile == null) { dailyFile = new ShopDataCrawlDailyFileEntity(); + dailyFile.setUserId(row.getUserId()); dailyFile.setShopKeyHash(shopKeyHash); dailyFile.setShopKey(shopKey); dailyFile.setBusinessDate(businessDate); diff --git a/backend-java/src/main/resources/db/V104__shop_data_crawl_daily_file_user_id_nullable.sql b/backend-java/src/main/resources/db/V104__shop_data_crawl_daily_file_user_id_nullable.sql new file mode 100644 index 00000000..225050af --- /dev/null +++ b/backend-java/src/main/resources/db/V104__shop_data_crawl_daily_file_user_id_nullable.sql @@ -0,0 +1,11 @@ +-- V104: 店铺数据抓取累计文件 user_id 改可空 +-- 背景:V95(97ae8a7)累计文件改为店铺级共享,persistDailyAggregation 已不再 +-- 写入 user_id(去 user 维度),但 V95 只改了唯一键,未把 user_id 列改可空。 +-- 新店铺首次插入 biz_shop_data_crawl_daily_file 时 MyBatis-Plus 对 null 的 +-- user_id 跳过该列 → INSERT 不含 user_id → 生产 MySQL 报 +-- "Field 'user_id' doesn't have a default value"(任务 26401 复现)。 +-- 已有 daily_file 行的店铺走 update 分支不受影响,因此该 bug 只出现在新店铺。 +-- 存量行(25 行)的 user_id 已是旧账号值,保留不动;唯一键 (shop_key,business_date) +-- 不含 user_id,可空不影响去重。 +ALTER TABLE biz_shop_data_crawl_daily_file + MODIFY COLUMN `user_id` BIGINT NULL DEFAULT NULL COMMENT '(V95 起不再使用,保留兼容)'; diff --git a/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlDailyFileIncrementalTest.java b/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlDailyFileIncrementalTest.java index a7fb149c..8ba765d4 100644 --- a/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlDailyFileIncrementalTest.java +++ b/backend-java/src/test/java/com/nanri/aiimage/modules/shopdatacrawl/service/ShopDataCrawlDailyFileIncrementalTest.java @@ -554,6 +554,10 @@ class ShopDataCrawlDailyFileIncrementalTest { assertEquals(1, dbDailyFiles.size(), "跨账号同店同日只保留一份累计文件"); assertEquals(3, dbMembers.size(), "三个结果各有一个成员行"); + // 回归:V95 把累计文件改为店铺级共享时误删了 setUserId,导致新建 + // daily_file 的 INSERT 不含 user_id(表列 NOT NULL 无默认值), + // 新店铺首次归档必报 Field 'user_id' doesn't have a default value。 + assertEquals(7L, dbDailyFiles.get(0).getUserId(), "新建累计文件必须写入 user_id"); // 整表重建:英国以最后一次(9503)为准,德国(9502)保留 triggerRebuild();