今天的工作主要围绕三个方向展开:报价导入 Bug 修复、碳排放指标问题排查,以及案例年份变更后的数据更新逻辑优化。整体下来,最大的收获是:后端开发不能只看"有没有写校验",更要看"校验的数据对象是不是最终真正落库的数据"。
一、报价导入 Bug:前置校验不等于最终数据安全
上午刚到工位,组长来找我反馈:昨天做的基础报价导入需求还有问题。
这个需求本身分成两个导入接口:一个是机组市场化报价导入,另一个是另一类报价导入。昨天我主要测试了机组市场化报价,功能正常;但今天组长反馈另一类报价导入存在边界校验 Bug。
我马上构造了 3 份测试 Excel 文件,分别覆盖正常值、边界值和越界值。测试后发现,问题确实存在:某些越界数据没有被拦截,最终还能进入后续处理流程。
一开始我比较疑惑,因为这两个接口底层走的是同一套抽象导入逻辑。我也检查了前置校验代码,逻辑看起来是完整的:在进入主处理流程前,会先判断 Excel 中的分段报价数据是否符合出力范围约束。
但问题恰好出在这里:前置校验校验的是 Excel 解析对象,而实际落库使用的是后续重新构造出来的分段报价对象。
也就是说,系统里存在两类对象:
- Excel 解析出来的导入 Bean
- 最终准备入库的分段报价实体列表
之前的校验发生在第一类对象上,但真正写入数据库的是第二类对象。两者之间经过了解析、字段映射和对象构造,如果这中间存在差异,就可能出现"前面校验通过,但最终落库对象仍然异常"的情况。
后面我调整了实现思路:不再只依赖 Excel 解析阶段的前置校验,而是在构造出最终要入库的分段报价数据之后,删除旧报价、插入新报价之前,再统一校验即将落库的数据。
这样改完之后,校验对象和落库对象保持一致,问题也就解决了。
这次修复里我主要做了几件事:
- 将校验位置后移到"最终分段报价对象构造完成后"
- 按设备 ID 关联报价数据、申报基础数据和模型数据
- 分别处理不同报价类型的边界规则
- 对额定容量、最小技术出力等关键字段增加空值保护
- 保证异常数据在数据库写入前被拦截
这次让我印象比较深的是:以前我会觉得"只要代码里写了校验就行",但这次发现,真正重要的是校验时机和校验对象。尤其是导入类需求,中间往往会经历 Excel 解析、DTO 转换、实体构造、批量入库等多个步骤,任何一步对象不一致,都可能导致校验失效。
二、碳排放月增长率显示为 0:不是所有页面异常都是接口 Bug
下午又排查了一个页面问题:页面上有一个"碳排放强度月增长率"一直显示为 0。
我第一反应是先确认数据源有没有问题,所以去数据库里构造了一批测试数据。构造完后发现,在某些条件下页面可以正常显示非 0 值,说明接口整体不是完全不可用。
接着我按照问题单里的查询条件复现,发现确实有些数据展示为 0。于是我继续看接口里的计算逻辑。
这个指标的计算方式是:
月增长率 = (本月强度 - 上月强度) / 上月强度
看完代码后发现接口逻辑本身没有问题。问题条件下,很多记录的本月强度和上月强度刚好相同,相减之后就是 0,所以页面显示 0 是符合业务计算逻辑的。
这个问题最后没有改代码,而是确认了接口计算逻辑和数据库数据。对我来说,这也是一次提醒:排查 Bug 时不能一看到页面显示异常就直接改接口,还是要先从数据、公式、条件和复现路径一步步确认。
三、年份范围变更:从全量删除改成按差异更新
后面我又做了一个案例数据更新需求。
原来的逻辑是:当页面上修改输入数据的年份范围后,系统会认为案例发生变化,因此需要清空相关视图表数据,同时删除数据库里的部分边界数据,要求用户重新导入。
旧实现比较粗暴:只要年份变化,就把城市发电量数据和城市月度分配系数都全量删除,然后重新初始化。
这次需求调整为:
- 发电量数据按年份差异处理
- 原来年份范围和新年份范围重叠的记录要保留
- 新增年份只初始化空白数据
- 被移除的年份才删除
- 城市月度分配系数不再删除,原有记录全部保留
这个需求实现难度不算大,但对数据处理思路有要求。核心不是简单地"删掉重建",而是要对新旧年份范围做集合差异计算。
我把逻辑拆成了三步:
- 根据旧年份范围生成旧年份集合
- 根据新年份范围生成新年份集合
- 对比两个集合,找出需要删除的年份和需要新增的年份
处理规则大概是:
旧范围有、新范围没有:删除对应年份的发电量数据 旧范围没有、新范围有:初始化对应年份的发电量数据 新旧范围都有:保留原数据
同时我也给更新方法补充了事务控制,避免在删除、新增、更新案例信息的过程中出现部分成功、部分失败的数据不一致问题。
这部分代码虽然不复杂,但我觉得比较有实际意义。因为它体现了后端开发里很常见的一个优化方向:从"全量重建"改成"增量维护"。这样既能保留用户已经维护过的数据,也能减少不必要的数据库操作。
四、今天的一个未完成点
最后组长还给了我一个新的需求:在已有最大节点价格、最小节点价格的基础上,补充平均节点价格的计算逻辑。
接口结构我已经看了一遍,最大值和最小值的计算逻辑不算复杂,但平均节点价格涉及多张表和业务口径。我目前还没有完全理解这些表之间的关系,也没有把需求 Excel 里的计算口径吃透,所以暂时没有贸然编码。
这件事也提醒我:有些需求不是"会写 Java"就能立刻做出来的。尤其是偏业务计算的接口,必须先搞清楚字段含义、数据来源和计算口径,否则写出来的代码很可能只是语法正确,但业务结果不可靠。
总结
今天最大的收获有三个:
第一,导入类需求的校验不能只看前置逻辑是否存在,更要确认校验对象是否和最终落库对象一致。
第二,排查页面问题时,要先验证数据和业务公式,不能默认页面显示异常就一定是接口 Bug。
第三,数据更新逻辑要尽量避免简单粗暴的全量删除,能按差异处理时,就应该保留有效数据,减少对用户已有数据的影响。