模型基类
基因提供者
GeneProvider 接口允许实体定义自己的业务基因
基因提供者
GeneProvider 接口允许每个实体类型定义自己的业务基因,在创建记录时自动使用对应的基因生成雪花 ID。
GeneProvider 接口
type GeneProvider interface {
// GetGene 返回实体的基因类型,用于生成雪花 ID 时指定业务基因
GetGene() xSnowflake.Gene
}工作原理
在 BaseEntity.BeforeCreate 钩子中,会检查实体是否实现了 GeneProvider 接口:
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)
}
// ...
}使用示例
实现接口
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
}type Order struct {
xModels.BaseEntityWithSoftDelete
OrderNo string `gorm:"type:varchar(64)"`
}
func (o *Order) GetGene() xSnowflake.Gene {
return xSnowflake.GeneOrder
}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):
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 计算基因,实现数据分片:
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)
}效果:
- 同一订单的所有商品项具有相同的基因值
- 便于按订单维度进行数据分片
- 查询同一订单的商品项时可以定位到同一分片
预定义基因
字段
类型
完整示例
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)