竹简文档
模型基类

基因提供者

GeneProvider 接口允许实体定义自己的业务基因

基因提供者

GeneProvider 接口允许每个实体类型定义自己的业务基因,在创建记录时自动使用对应的基因生成雪花 ID。

GeneProvider 接口

provider.go
type GeneProvider interface {
    // GetGene 返回实体的基因类型,用于生成雪花 ID 时指定业务基因
    GetGene() xSnowflake.Gene
}

工作原理

BaseEntity.BeforeCreate 钩子中,会检查实体是否实现了 GeneProvider 接口:

base_entity.go
func (e *BaseEntity) BeforeCreate(tx *gorm.DB) error {
    if e.ID.IsZero() {
        // 默认使用 GeneDefault
        gene := xSnowflake.GeneDefault
        // 检查实体是否实现了 GeneProvider 接口
        if provider, ok := tx.Statement.Dest.(GeneProvider); ok {
            gene = provider.GetGene()
        }
        e.ID = xSnowflake.GenerateID(gene)
    }
    // ...
}

使用示例

实现接口

entity/user.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 User struct {
    xModels.BaseEntity
    Username string `gorm:"type:varchar(64)"`
}

// 实现 GeneProvider 接口
func (u *User) GetGene() xSnowflake.Gene {
    return xSnowflake.GeneUser
}
entity/order.go
type Order struct {
    xModels.BaseEntityWithSoftDelete
    OrderNo string `gorm:"type:varchar(64)"`
}

func (o *Order) GetGene() xSnowflake.Gene {
    return xSnowflake.GeneOrder
}
entity/payment.go
type Payment struct {
    xModels.BaseEntity
    Amount int64 `gorm:"type:bigint"`
}

func (p *Payment) GetGene() xSnowflake.Gene {
    return xSnowflake.GenePayment
}

创建记录

// 创建用户,ID 会使用 GeneUser 基因
user := &entity.User{Username: "zhangsan"}
db.Create(user)
fmt.Println(user.ID.Gene()) // User

// 创建订单,ID 会使用 GeneOrder 基因
order := &entity.Order{OrderNo: "ORD001"}
db.Create(order)
fmt.Println(order.ID.Gene()) // Order

// 创建支付,ID 会使用 GenePayment 基因
payment := &entity.Payment{Amount: 9900}
db.Create(payment)
fmt.Println(payment.ID.Gene()) // Payment

不实现接口

如果实体不实现 GeneProvider 接口,会使用默认基因 GeneDefault(0)

entity/log.go
type Log struct {
    xModels.BaseEntity
    Message string `gorm:"type:text"`
}

// 不实现 GeneProvider,使用默认基因
log := &entity.Log{Message: "操作日志"}
db.Create(log)
fmt.Println(log.ID.Gene()) // Default

基因分片

可以使用 GeneCalc 基于关联 ID 计算基因,实现数据分片:

entity/order_item.go
type OrderItem struct {
    xModels.BaseEntity
    OrderID   xSnowflake.SnowflakeID `gorm:"type:bigint;index"`
    ProductID xSnowflake.SnowflakeID `gorm:"type:bigint"`
    Quantity  int                    `gorm:"type:int"`
}

// 基于订单 ID 计算基因,同一订单的商品项具有相同基因
func (o *OrderItem) GetGene() xSnowflake.Gene {
    return xSnowflake.CalcGene().Hash(o.OrderID)
}

效果:

  • 同一订单的所有商品项具有相同的基因值
  • 便于按订单维度进行数据分片
  • 查询同一订单的商品项时可以定位到同一分片

预定义基因

字段

类型

完整示例

entity/merchant.go
package entity

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

// 自定义基因常量
const GeneMerchant xSnowflake.Gene = 32

type Merchant struct {
    xModels.BaseEntityWithSoftDelete
    Name    string `gorm:"type:varchar(128)" json:"name"`
    Contact string `gorm:"type:varchar(64)" json:"contact"`
    Status  int    `gorm:"type:smallint;default:1" json:"status"`
}

// 使用自定义基因
func (m *Merchant) GetGene() xSnowflake.Gene {
    return GeneMerchant
}
// 创建商户
merchant := &entity.Merchant{
    Name:    "测试商户",
    Contact: "13800138000",
}
db.Create(merchant)

// 从 ID 识别数据类型
fmt.Println(merchant.ID.Gene()) // Custom(32)

下一步

On this page