diff --git a/muse-cloud/muse-module-content/muse-module-content-server/src/main/java/cn/iocoder/muse/module/content/dal/mysql/PlanningFieldSnapshotMapper.java b/muse-cloud/muse-module-content/muse-module-content-server/src/main/java/cn/iocoder/muse/module/content/dal/mysql/PlanningFieldSnapshotMapper.java index bc62b704..346df2eb 100644 --- a/muse-cloud/muse-module-content/muse-module-content-server/src/main/java/cn/iocoder/muse/module/content/dal/mysql/PlanningFieldSnapshotMapper.java +++ b/muse-cloud/muse-module-content/muse-module-content-server/src/main/java/cn/iocoder/muse/module/content/dal/mysql/PlanningFieldSnapshotMapper.java @@ -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 { - /** 删除某 section 的旧快照(保存 planning 时先删后写,保证重复保存幂等)。 */ - default int deleteBySectionId(Long sectionId) { - return delete(new LambdaQueryWrapperX() - .eq(PlanningFieldSnapshotDO::getSectionId, sectionId)); - } + /** + * 物理删除某 section 的旧快照(保存 planning 时先删后写,保证重复保存幂等)。 + * + *

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 全局唯一,双重隔离。

+ */ + @Delete("DELETE FROM muse_content_planning_field_snapshot WHERE section_id = #{sectionId}") + int deleteBySectionId(@Param("sectionId") Long sectionId); /** 查某 section 现有快照(测试 / 校验用)。 */ default List selectListBySectionId(Long sectionId) {