竹简文档
模型基类

软删除实体

BaseEntityWithSoftDelete 提供逻辑删除支持

软删除实体

BaseEntityWithSoftDeleteBaseEntity 基础上增加了软删除支持,删除操作不会物理删除数据,而是设置删除时间戳。

BaseEntityWithSoftDelete

base_entity_soft_delete.go
type BaseEntityWithSoftDelete struct {
    ID        xSnowflake.SnowflakeID `json:"id" gorm:"type:bigint;primaryKey;comment:主键"`
    CreatedAt time.Time              `json:"-" gorm:"autoCreateTime:milli;not null;comment:创建时间"`
    UpdatedAt time.Time              `json:"updated_at" gorm:"autoUpdateTime:milli;not null;comment:更新时间"`
    DeletedAt gorm.DeletedAt         `json:"-" gorm:"type:timestamp;index;comment:删除时间"`
}

字段说明

字段

类型

与 BaseEntity 的区别

特性BaseEntityBaseEntityWithSoftDelete
软删除支持
DeletedAt 字段gorm.DeletedAt
删除行为物理删除逻辑删除
查询行为查询所有记录自动过滤已删除记录

使用示例

定义实体

entity/order.go
package entity

import (
    xModels "github.com/bamboo-services/bamboo-base-go/major/models"
    xSnowflake "github.com/bamboo-services/bamboo-base-go/common/snowflake"
)

type Order struct {
    xModels.BaseEntityWithSoftDelete              // 继承软删除实体
    UserID  xSnowflake.SnowflakeID `json:"user_id" gorm:"type:bigint;index"`
    OrderNo string                 `json:"order_no" gorm:"type:varchar(64);uniqueIndex"`
    Amount  int64                  `json:"amount" gorm:"type:bigint"`
}

func (o *Order) GetGene() xSnowflake.Gene {
    return xSnowflake.GeneOrder
}

创建记录

order := &entity.Order{
    UserID:  userID,
    OrderNo: "ORD202401150001",
    Amount:  9900,
}

db.Create(order)

软删除

// 软删除:设置 DeletedAt 为当前时间,不物理删除
db.Delete(&order)

// 数据库中:
// deleted_at = '2024-01-15 10:30:00'

查询记录

var orders []entity.Order

// 普通查询:自动过滤已删除记录
db.Find(&orders)

// 查询包含已删除的记录
db.Unscoped().Find(&orders)

// 只查询已删除的记录
db.Unscoped().Where("deleted_at IS NOT NULL").Find(&orders)

恢复数据

// 恢复已删除的记录
db.Unscoped().Model(&order).Update("deleted_at", nil)

物理删除

// 真正删除数据(慎用)
db.Unscoped().Delete(&order)

数据库表结构

使用 BaseEntityWithSoftDelete 的实体会生成如下表结构:

CREATE TABLE orders (
    id         BIGINT PRIMARY KEY,
    created_at TIMESTAMP(3) NOT NULL,
    updated_at TIMESTAMP(3) NOT NULL,
    deleted_at TIMESTAMP,              -- 软删除字段
    user_id    BIGINT,
    order_no   VARCHAR(64) UNIQUE,
    amount     BIGINT
);

-- 软删除字段索引
CREATE INDEX idx_orders_deleted_at ON orders(deleted_at);

软删除机制

删除操作

// 调用 Delete
db.Delete(&order)

// 实际执行的 SQL
// UPDATE orders SET deleted_at = '2024-01-15 10:30:00' WHERE id = ?

查询操作

// 普通查询
db.Find(&orders)

// 实际执行的 SQL
// SELECT * FROM orders WHERE deleted_at IS NULL

Unscoped 查询

// 忽略软删除条件
db.Unscoped().Find(&orders)

// 实际执行的 SQL
// SELECT * FROM orders

最佳实践

选择合适的基类

场景推荐基类
用户数据BaseEntityWithSoftDelete
订单数据BaseEntityWithSoftDelete
日志数据BaseEntity
配置数据BaseEntity
临时数据BaseEntity

软删除注意事项

// 1. 唯一索引问题:软删除后唯一索引仍然生效
// 解决方案:使用复合唯一索引包含 deleted_at

type User struct {
    xModels.BaseEntityWithSoftDelete
    // 复合唯一索引,允许同名用户(一个已删除,一个未删除)
    Username string `gorm:"type:varchar(64);uniqueIndex:idx_username_deleted"`
}

// 2. 关联查询:关联表也需要考虑软删除
db.Preload("Orders", "deleted_at IS NULL").Find(&users)

下一步

On this page