chore(db): V17 审计并补齐软删除与 FK 一致性

This commit is contained in:
2026-07-07 18:58:51 +08:00
parent 4dbc190f68
commit f88230687c
7 changed files with 120 additions and 42 deletions

View File

@@ -1,24 +1,15 @@
package com.sino.mci.admin.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sino.mci.shared.entity.BaseEntity;
import lombok.Data;
import java.time.LocalDateTime;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mci_user_role")
public class UserRole {
@TableId(type = IdType.AUTO)
private Long id;
public class UserRole extends BaseEntity {
private Long userId;
private Long roleId;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}

View File

@@ -5,6 +5,12 @@ import com.sino.mci.shared.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 会话表mci_conversation
* <p>
* 该表在 V15 已按 create_time 做 RANGE 月分区MySQL 分区表不支持数据库级外键,
* 因此与会话相关的外键已在 V15 全部移除。引用完整性由应用层MyBatis-Plus 逻辑删除 + 业务校验)维护。
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mci_conversation")

View File

@@ -1,23 +1,20 @@
package com.sino.mci.channel.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sino.mci.shared.entity.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mci_conversation_participant")
public class ConversationParticipant {
@TableId(type = IdType.AUTO)
private Long id;
public class ConversationParticipant extends BaseEntity {
private Long conversationId;
private Long personId;
private Long channelIdentityId;
private Integer participantType;
private LocalDateTime joinTime;
private LocalDateTime createTime;
}

View File

@@ -1,21 +1,16 @@
package com.sino.mci.channel.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sino.mci.shared.entity.BaseEntity;
import lombok.Data;
import java.time.LocalDateTime;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mci_conversation_tag_binding")
public class ConversationTagBinding {
@TableId(type = IdType.AUTO)
private Long id;
public class ConversationTagBinding extends BaseEntity {
private String tenantCode;
private Long tagId;
private Long conversationId;
private LocalDateTime createTime;
}

View File

@@ -1,21 +1,16 @@
package com.sino.mci.crm.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sino.mci.shared.entity.BaseEntity;
import lombok.Data;
import java.time.LocalDateTime;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mci_person_tag_binding")
public class PersonTagBinding {
@TableId(type = IdType.AUTO)
private Long id;
public class PersonTagBinding extends BaseEntity {
private String tenantCode;
private Long tagId;
private Long personId;
private LocalDateTime createTime;
}

View File

@@ -1,13 +1,15 @@
package com.sino.mci.inbound.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.sino.mci.shared.entity.BaseEntity;
import lombok.Data;
import java.time.LocalDateTime;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("mci_flow_execution_trace")
public class FlowExecutionTrace {
private Long id;
public class FlowExecutionTrace extends BaseEntity {
private String eventId;
private Long flowDefinitionId;
private String nodeType;
@@ -17,5 +19,4 @@ public class FlowExecutionTrace {
private Integer status;
private Integer durationMs;
private String errorMsg;
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,93 @@
-- Phase 1.6: 审计并补齐软删除/FK 一致性
-- 目标:
-- 1. 所有业务表必须具备 deleted 字段;对应实体继承 BaseEntity含 @TableLogic 与自动填充)。
-- 2. 唯一索引在软删除表中必须包含 deleted避免已删除记录导致唯一冲突。
-- 3. 记录 V15 分区改造后 mci_conversation 及其关联表不再支持数据库级外键的事实
-- MySQL 分区表不支持外键,应用层通过 MyBatis-Plus 逻辑删除保证引用完整性)。
-- ============================
-- 1. 补齐缺少 deleted/update_time 的业务表
-- ============================
-- 用户角色关系表
ALTER TABLE mci_user_role
ADD COLUMN update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER create_time,
ADD COLUMN deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除0未删除 1已删除' AFTER update_time;
-- 会话参与者表
ALTER TABLE mci_conversation_participant
ADD COLUMN update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER create_time,
ADD COLUMN deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除0未删除 1已删除' AFTER update_time;
-- 人员标签绑定表
ALTER TABLE mci_person_tag_binding
ADD COLUMN update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER create_time,
ADD COLUMN deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除0未删除 1已删除' AFTER update_time;
-- 会话标签绑定表
ALTER TABLE mci_conversation_tag_binding
ADD COLUMN update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER create_time,
ADD COLUMN deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除0未删除 1已删除' AFTER update_time;
-- 流程执行轨迹表
ALTER TABLE mci_flow_execution_trace
ADD COLUMN update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER create_time,
ADD COLUMN deleted TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除0未删除 1已删除' AFTER update_time;
-- ============================
-- 2. 统一唯一索引:软删除表的唯一索引必须包含 deleted
-- ============================
-- mci_tenant: 租户编码唯一(排除已删除)
ALTER TABLE mci_tenant
DROP INDEX tenant_code,
ADD UNIQUE KEY uk_tenant_code (tenant_code, deleted);
-- mci_platform_role: 角色编码唯一(排除已删除)
ALTER TABLE mci_platform_role
DROP INDEX role_code,
ADD UNIQUE KEY uk_role_code (role_code, deleted);
-- mci_user_role: 同一用户同一角色仅允许一条生效记录
ALTER TABLE mci_user_role
DROP INDEX uk_user_role,
ADD UNIQUE KEY uk_user_role (user_id, role_id, deleted);
-- mci_conversation_participant: 同一身份在同一会话中仅允许一条生效记录
ALTER TABLE mci_conversation_participant
DROP INDEX uk_conv_participant,
ADD UNIQUE KEY uk_conv_participant (conversation_id, person_id, channel_identity_id, deleted);
-- mci_channel_account_conversation: 同一账号同一会话同一绑定类型仅允许一条生效记录
ALTER TABLE mci_channel_account_conversation
DROP INDEX uk_account_conv_binding,
ADD UNIQUE KEY uk_account_conv_binding (account_id, conversation_id, binding_type, deleted);
-- mci_person_tag_binding: 同一标签同一人员仅允许一条生效记录
ALTER TABLE mci_person_tag_binding
DROP INDEX uk_person_tag,
ADD UNIQUE KEY uk_person_tag (tag_id, person_id, deleted);
-- mci_conversation_tag_binding: 同一标签同一会话仅允许一条生效记录
ALTER TABLE mci_conversation_tag_binding
DROP INDEX uk_conversation_tag,
ADD UNIQUE KEY uk_conversation_tag (tag_id, conversation_id, deleted);
-- mci_message_event: event_id 唯一(保留分区键 create_time
ALTER TABLE mci_message_event
DROP INDEX uk_event_id,
ADD UNIQUE KEY uk_event_id (event_id, deleted, create_time);
-- mci_send_record: 任务维度唯一(保留分区键 create_time
ALTER TABLE mci_send_record
DROP INDEX uk_task_target,
ADD UNIQUE KEY uk_task_target (task_id, conversation_id, person_id, deleted, create_time);
-- ============================
-- 3. 分区表外键声明
-- ============================
-- V15 已完成 mci_conversation 分区改造,并删除了与会话表相关的数据库级外键约束:
-- fk_participant_conversation_id、fk_binding_conversation_id、fk_conv_tag_conversation_id、
-- fk_conversation_owner_account、fk_conversation_subject_id。
-- 本迁移再次明确mci_conversation 为 RANGE 分区表MySQL 分区表不支持外键;
-- 应用层通过 MyBatis-Plus 逻辑删除与业务校验维护引用完整性,不再恢复数据库级级联约束。