SQL与代码一致性核对报告.md 15 KB

SQL 与代码一致性核对报告

核对日期:2026-06-18 核对范围:sql/ 目录下全部初始化脚本 + sql/migrations/2026-06-17-autofocus-data-layer.sql 核对对象:各微服务 MyBatis 实体/Mapper(@TableName)、C# 控制端 SqlSugar 实体([SugarColumn]) 性质:只读核对,未改动任何 SQL/代码 结论摘要:base 脚本表名覆盖基本一致;本次对焦改造的列在“中央端 MySQL(Java tl-control)”侧完全缺失,是本次最关键的不一致。

🔄 校正注(2026-06-18 体检补记):上面"中央端列完全缺失"为核对时点结论;V-047 已补全——Java tl-control 实体现已含对焦列(TlSetting.java:289 focus_layer_spacing_pulse / :295 focus_layer_countHouseWellSetting.java:59 move_down_layer / :82 focus_layer_spacing_pulse / :88 focus_layer_count),下发 VO/DTO/mapper 与 C# DTO 重载同步补齐,随四微服务编译通过。该项不一致已消解,运行/真机待验(V-047/V-064)。本节下文逐列核对保留为历史依据。


一、库脚本 ↔ 微服务 ↔ 关键表 对应总表

sql 脚本 目标库 微服务 数据源(jdbc) 脚本表数 代码 @TableName 覆盖
aivfo-auth.sql aivfo-auth aivfo-gateway(认证) 4 (middle/permission/role/user) 4 全覆盖 ✅
aivfo_services.sql aivfo_services aivfo-service jdbc:mysql://.../aivfo_services 2 (alarm_contacts/tdi_log) ⚠ 见 §四-3:代码实际只用 msg_send_info,脚本里的两表无对应实体
aivfo-tl.sql(中划线) aivfo-tl aivfo-data-transmission jdbc:mysql://.../aivfo-tl 4 (video/video_pictures/video_splice/video_update) ⚠ 见 §四-2:另有 picture/picture_identify_result DAO 指向同库但脚本无此两表
aivfo_tl.sql(下划线) aivfo_tl aivfo-business-manage (加密 jdbcUrl) 25 (病例/胚胎/字典) ⚠ 见 §四-1:identify_key 实体/Mapper 在用,但脚本里是 mark_key,无 identify_key
aivfo_tl_setting.sql aivfo_tl_setting aivof-tl-control (加密 jdbcUrl) 17 (告警/区域/拍照设置) 15 个 @TableName 全部在脚本中存在 ✅
log.sql log aivfo-log 框架 1 (system_log) 框架表,未逐核
quartz.sql quartz aivfo-quartz 框架 11 (tqrtz*) 框架表,未逐核

C# 控制端(ivf_tl_control_2.0)使用本地 SQLiteDependFile\DB\aivfoTL.db,见 AppData.cs:86),不连上述 MySQL;表通过 SqlSugar 实体映射。详见 §二、§三。


二、本次改造新增表逐列核对:house_autofocus_calibration

对比对象:

  • MySQL 迁移脚本 sql/migrations/2026-06-17-autofocus-data-layer.sqlCREATE TABLE house_autofocus_calibration
  • C# 实体 ivf_tl_control_2.0/ivf_tl_Entity/DBEntitys/HouseAutofocusCalibrationDB.cs[SugarTable("house_autofocus_calibration")]
迁移脚本列 类型(MySQL) C# 属性 C# 映射列名 C# 类型 一致性
id bigint AI PK id id (PK,Identity) long
tl_sn varchar(255) NOT NULL tlSn tl_sn string
house_sn int NOT NULL houseSn house_sn int
well_sn int NOT NULL wellSn well_sn int
scene int NOT NULL scene scene int
focus_z int NOT NULL focusZ focus_z int
exposure int NULL exposure exposure int?
horizontal_pulse int NULL horizontalPulse horizontal_pulse int?
peak_ratio decimal(10,3) NULL peakRatio peak_ratio decimal?
circle_found tinyint NULL circleFound circle_found int? ✅ (tinyint↔int 兼容)
center_offset_pct decimal(10,3) NULL centerOffsetPct center_offset_pct decimal?
calib_time datetime NOT NULL calibTime calib_time DateTime
source varchar(32) NOT NULL DEFAULT 'LOCAL_JSON' source source string ✅ (默认值仅脚本侧)
note varchar(255) NULL note note string
create_by varchar(255) NULL createBy create_by string
create_time datetime NULL createTime create_time DateTime?
update_by varchar(255) NULL updateBy update_by string
update_time datetime NULL updateTime update_time DateTime?
deleted timestamp NULL deleted deleted DateTime?
platform_id int NULL platformId platform_id int?

结论:house_autofocus_calibration 表 20 列与 C# 实体逐列完全一致 ✅。

补充说明:

  • 本地 SQLite 端该表由 DBService.StartDbService()Db.CodeFirst.InitTables(typeof(HouseAutofocusCalibrationDB)) 自动建表(DBService.cs:59),CREATE TABLE IF NOT EXISTS,已建则不动。这是 sql 目录里唯一一处由 C# CodeFirst 建、且不需要手工跑迁移脚本的表(本地侧)。
  • 中央端 MySQL 侧该镜像表需手工执行迁移脚本建立(见 §五)。但目前没有任何 Java 实体/Mapper 引用 house_autofocus_calibration(全仓 grep 0 命中)——即中央端这张表当前没有服务读写它,只是“预留镜像位”。属设计预期(真相源在机旁 calibration.json),非缺陷,但需知晓。

三、本次改造扩列逐列核对(tl_setting + house_well_setting)

3.1 tl_setting 扩 5 列 ↔ C# TLSettingDB.cs

迁移脚本新增列 类型 默认 C# 属性(TLSettingDB) 一致性
focus_layer_spacing_pulse int NULL NULL int? focusLayerSpacingPulse
focus_layer_count int NOT NULL 5 int? focusLayerCount ⚠ 列名/类型对应;脚本 NOT NULL+默认5,C# 为可空(IsNullable=true)。SQLite 本地缓存可空属设计,但与 MySQL NOT NULL 语义不同
focus_layer_down int NOT NULL 2 int? focusLayerDown ⚠ 同上(脚本 NOT NULL,C# 可空)
focus_peak_ratio_threshold decimal(10,3) NOT NULL 1.200 decimal? focusPeakRatioThreshold ⚠ 同上(脚本 NOT NULL,C# 可空)
local_autofocus_enabled int NOT NULL 0 int localAutofocusEnabled (非空)

C# 端列名映射:未写 [SugarColumn(ColumnName=...)],沿用本表 camelCase 直映风格([SugarTable("TLSettingDB")],整表是 camelCase 列名,与 MySQL 蛇形不同库不同表,互不冲突)。

3.2 house_well_setting 扩 2 列 ↔ C# HouseWellSettingDB.cs

迁移脚本新增列 类型 C# 属性(HouseWellSettingDB) 一致性
focus_layer_spacing_pulse int NULL int? focusLayerSpacingPulse
focus_layer_count int NULL int? focusLayerCount

C# 端同样 camelCase 直映,[SugarTable("HouseWellSettingDB")]。下移层数复用既有 moveDownLayer,未新增列,与脚本注释一致 ✅。

3.3 ⚠⚠ 关键一致性问题:对焦列在“中央端 MySQL” vs “本地 SQLite”的来源

这是本次核对发现的最重要问题,务必关注:

维度 现状
迁移脚本方言 MySQL,注释明确“库:aivfo_tl_setting(中央端 tl_setting 库)”
C# 控制端实际读哪个库 本地 SQLiteaivfoTL.db)。取数链:DBService.DBUpdateTLInfo()ConvertHelper.ConvertToTLSettingDB(tLInitControllerResult.TLSetting)服务器下发的 init JSON 转成 TLSettingDB 写入本地 SQLite;运行时再 ConvertToTLSetting() 回填到运行态 TLSettingConvertHelper.cs:144-147, 223-226),喂给 HouseBin.cs 拍照层计算
本地 SQLite 的 tl_setting/house_well_setting 表结构在哪定义? 未发现显式定义DBService.StartDbService 只对 HouseAutofocusCalibrationDB 调了 InitTables没有对 TLSettingDB/HouseWellSettingDB 调 InitTables。即本地 SQLite 这两张表的新列不会被自动加列——若本地 db 文件是旧结构,写入/读取新列会失败或丢列
中央端来源(关键断链) C# 注释写“取数链同 focusLayer*:经服务器 init JSON 反序列化”(TLSetting.cs:385)。但服务器端 Java TlSetting.java 实体完全没有这 5 列(见下)

断链证据(全仓 grep):

  • Java 侧 focus_layer* / focusLayer* / local_autofocus* / focus_peak* 命中数 = 0(aivof-tl-control、aivfo-business-manage 全模块,含 .java 与 mapper .xml)。
  • aivof-tl-control/.../entity/dao/TlSetting.java 实体最后一列是 operable_embryo_time无任何对焦扩列
  • 即:中央端 MySQL 即使按迁移脚本加了 5 列,Java 也不会 SELECT 出来、也不会放进下发给 C# 的 init JSON → C# 端 focusLayerSpacingPulse 永远收不到值 → 按 TLSetting.cs:347 设计将为 null → §2.5 抛 FocusConfigMissingException(不兜底)。

回答任务三问:

  1. C# 端这些对焦列是从本地 SQLite 读(TLSettingDB/HouseWellSettingDB),值来源是服务器 init JSON 下发后缓存
  2. sql/aivfo_tl_setting.sql 的 tl_setting 需要也加这 5 列(给中央端 MySQL)——迁移脚本正是为此而写;但仅加列还不够,必须同步给 Java 端 TlSetting.java/HouseWellSetting.java@TableField,否则下发链断裂。
  3. 本地 SQLite 的 tl_setting 表结构没有显式建表/迁移代码,新列存在“本地旧 db 不会自动加列”的风险(见 §四-4)。

四、发现的不一致 / 缺口 / 风险

⚠ 风险1【最高】中央端 Java 实体缺对焦 5+2 列 → 下发链断裂

  • TlSetting.javaHouseWellSetting.java(aivof-tl-control)均无 focuslayer* / local_autofocus_enabled 字段。
  • 后果:迁移脚本给 MySQL 加了列,但 Java ORM 读不到、init JSON 下发不出去,C# 端拿不到对焦配置,本地对焦走报错或降级。
  • 处置建议(不在本次范围,仅记录):需给 Java TlSetting/HouseWellSetting 补 5+2 个 @TableField,并在下发 init JSON 的组装链路带上这些字段。

⚠ 风险2 data-transmission:picture / picture_identify_result 无对应建表

  • PictureDAO(@TableName picture)、PictureIdentifyResultDAO(@TableName picture_identify_result) 指向 aivfo-tl 库,但 sql/aivfo-tl.sql 只有 4 张 video 表。
  • 这两张表的 CREATE 在 aivfo_tl.sql(下划线,business 库)里存在。若 data-transmission 确实需要在 aivfo-tl(中划线)库读写它们,则该库缺表;若是历史遗留 DAO 不再使用,则脚本无需补。需业务确认这两个 DAO 是否仍在运行链路中。

⚠ 风险3 aivfo_services.sql 表与代码不对应

  • 脚本含 alarm_contacts / tdi_log 两表;但 aivfo-service 代码里无 AlarmContacts/TdiLog 实体,全仓 grep alarm_contacts 在 .java 中 0 命中。
  • 服务实际使用的是 msg_send_infoMsgSendInfo.java@TableName msg_send_info),而该表不在 aivfo_services.sql 中
  • 即 services 库脚本与代码双向不匹配:脚本多了 2 张无人用的表,代码用的 msg_send_info 脚本里没有。需确认 msg_send_info 的建表脚本来源(可能在别处或漏导出)。

⚠ 风险4 business-manage:identify_key 表缺失

  • IdentifyKey.java + IdentifyKeyMapper(BaseMapper) 映射 @TableName identify_key,被 AutoMark 处理器链使用。
  • sql/aivfo_tl.sql CREATE TABLE identify_key(只有 mark_key,且 identify_key 仅作为列名出现)。属脚本缺表(或表名与代码不一致)。需确认 identify_key 是否应有独立建表。

⚠ 风险5 本地 SQLite tl_setting/house_well_setting 不自动迁移新列

  • DBService.StartDbServiceInitTables(HouseAutofocusCalibrationDB),未对 TLSettingDB/HouseWellSettingDB 做 CodeFirst 迁移。
  • 现网若 aivfoTL.db 为旧结构,新对焦列在本地表中不存在 → SqlSugar 写/读这些列会异常或被忽略。需确认本地 db 升级方式(重建 db / 手工 ALTER / 补 InitTables)。 该项已被项目登记为待验证 V-046/V-047。

一致项(无风险)

  • house_autofocus_calibration:脚本 20 列与 C# 实体逐列一致 ✅。
  • tl_setting / house_well_setting 扩列:列名语义与 C# 属性一一对应 ✅(仅 NOT NULL vs 可空的语义差异,见 §3.1)。
  • aivof-tl-control 15 个 @TableName 全部在 aivfo_tl_setting.sql 中存在 ✅。
  • aivfo-auth 4 表、gateway 4 个 @TableName 一致 ✅。
  • house_autofocus_calibration 正确地不在任何 base 脚本中(本地 CodeFirst 建 + 中央端走 migration)✅。

精简测试数据.sql(简核)

  • 仅做数据清理/种子:DELETE/TRUNCATE 流水表(video/picture/embryo_culture_record/alarm_data/tdi_log/system_log/log/message 等),INSERT 少量保留种子(keep_case/keep_dev/keep_record/keep_video)。
  • 与“配置/字典/多语言完整保留、流水清空”的精简主线一致 ✅;不涉及对焦新表/新列,无冲突。

五、部署时 SQL 执行建议

  1. base 与 migration 必须分开两步执行sql/aivfo_tl_setting.sql(base)当前 tl_setting/house_well_setting 不含 focuslayer* / local_autofocus_enabled 列;这些列只在 sql/migrations/2026-06-17-autofocus-data-layer.sql 中。
    • 执行顺序:先导入 base 脚本(建库建表+种子)→ 再对 同一个 aivfo_tl_setting 执行 migration 脚本(新增 house_autofocus_calibration 表 + ALTER 两表加列)。
  2. migration 目标库 = aivfo_tl_setting(脚本头注释已写明),不要误跑到 aivfo_tl/aivfo-tl
  3. migration 不可重复执行:脚本用 DROP TABLE IF EXISTS house_autofocus_calibration(会清空已建镜像表),且 MySQL 8 ADD COLUMN 不支持 IF NOT EXISTS,重跑 ALTER 会报“列已存在”。重跑前需人工判断列/表是否已存在。
  4. 本地 SQLite(C#)侧:house_autofocus_calibration 由程序启动时 CodeFirst 自动建,无需手工跑 migration;但 tl_setting/house_well_setting 的新列在本地 SQLite 无自动迁移——部署到旧机器前需确认本地 db 是否需重建或手工 ALTER(风险5)。
  5. 遗留前置(强烈建议先解决,否则对焦配置链路不通):在依赖中央端下发对焦配置前,须先给 Java TlSetting/HouseWellSetting 补字段(风险1)。仅跑 SQL migration 不能让 C# 端拿到对焦配置。

六、是否符合代码要求 —— 总判定

  • 本次改造新增/改动的“数据库结构”层面:house_autofocus_calibration 表、tl_setting/house_well_setting 扩列,与 C# 控制端 SqlSugar 实体对应关系 基本一致(结构层符合)
  • 但“整条配置流通链路”不符合代码要求:迁移脚本是 MySQL 方言、面向中央端 tl_setting 库;而中央端 Java tl-control 实体/Mapper 完全没有这些对焦列,导致“DB 加列 → Java 读取 → init JSON 下发 → C# 本地缓存”链路在 Java 环节断裂。C# 端虽已就绪,但拿不到中央端下发的对焦配置。
  • 另发现 3 处既有的脚本↔代码不匹配(identify_key 缺表、aivfo_services 表与 msg_send_info 不对应、data-transmission picture 系表归属),属本次改造之外的历史缺口,一并记录待确认。