fix(content): planning 字段快照物理删除,修二次保存重复键 500
captureFieldSnapshot 的 deleteBySectionId 原走 MyBatis-Plus 逻辑删除(@TableLogic): 被删物理行(deleted=TRUE)仍占唯一约束 uk(tenant_id,section_id,field_key)(不含 deleted), 用户二次保存同 section 字段时 INSERT 撞键→DuplicateKeyException→规划保存 500。 改原生 @Delete 物理清行,根治幂等(快照是可重建派生数据,物理删除无审计损失)。 根因:全量 e2e 暴露 planning-edit save 500(work-schema-binding 为并发 flaky,单跑绿)。 验证:planning-edit e2e 真后端 1 passed;连续 2 次 save 同 section code=0(rev 3→4,旧 jar 第 2 次必 500)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
494f3b5fd6
commit
a9323adb13
@ -3,7 +3,9 @@ package cn.iocoder.muse.module.content.dal.mysql;
|
||||
import cn.iocoder.muse.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.muse.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.muse.module.content.dal.dataobject.PlanningFieldSnapshotDO;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -17,11 +19,16 @@ import java.util.List;
|
||||
@Mapper
|
||||
public interface PlanningFieldSnapshotMapper extends BaseMapperX<PlanningFieldSnapshotDO> {
|
||||
|
||||
/** 删除某 section 的旧快照(保存 planning 时先删后写,保证重复保存幂等)。 */
|
||||
default int deleteBySectionId(Long sectionId) {
|
||||
return delete(new LambdaQueryWrapperX<PlanningFieldSnapshotDO>()
|
||||
.eq(PlanningFieldSnapshotDO::getSectionId, sectionId));
|
||||
}
|
||||
/**
|
||||
* 物理删除某 section 的旧快照(保存 planning 时先删后写,保证重复保存幂等)。
|
||||
*
|
||||
* <p>WHY 物理删除而非 MyBatis-Plus 逻辑删除:本表是字段用量投影(可重建的派生数据、无审计价值),
|
||||
* 唯一约束 uk(tenant_id, section_id, field_key) 不含 deleted 列。若走 @TableLogic 逻辑删除,
|
||||
* 被删的物理行(deleted=TRUE)仍占用 uk,再次保存同字段时 INSERT 必撞唯一键→DuplicateKeyException(二次保存即 500)。
|
||||
* 故用原生 DELETE 清干净物理行;tenant 插件会对该 DELETE 追加 tenant_id 条件,且 section_id 全局唯一,双重隔离。</p>
|
||||
*/
|
||||
@Delete("DELETE FROM muse_content_planning_field_snapshot WHERE section_id = #{sectionId}")
|
||||
int deleteBySectionId(@Param("sectionId") Long sectionId);
|
||||
|
||||
/** 查某 section 现有快照(测试 / 校验用)。 */
|
||||
default List<PlanningFieldSnapshotDO> selectListBySectionId(Long sectionId) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user