Cor*_*urn 9 foreign-keys go go-gorm
Gorm 对外键的半生不熟、开箱即用的支持多年来一直令人烦恼,我终于试图一劳永逸地解决它。我正在使用 Postgres 12、gorm 1.23.3 和 go 1.18。
我有一个类似于gorm.Model但有一点额外的基本模型:
type BaseModel struct {
ID string `json:"id" gorm:"type:uuid;primarykey;default:uuid_generate_v4()"`
InstanceVersion int `json:"instanceVersion"`
CreatedAt time.Time `json:"createdAt" gorm:"type:timestamp"`
UpdatedAt time.Time `json:"updatedAt" gorm:"type:timestamp"`
DeletedAt *time.Time `json:"deletedAt,omitempty" gorm:"type:timestamp" sql:"index"`
CreatedBy string `json:"createdBy"`
UpdatedBy string `json:"updatedBy"`
DeletedBy string `json:"deletedBy,omitempty"`
MetaData json.RawMessage `json:"metadata" gorm:"type:jsonb;default:'{}'"`
}
Run Code Online (Sandbox Code Playgroud)
我的数据库中的每个模型都使用它,BaseModel如下所示:
type Profile struct {
BaseModel
Name string `json:"name"`
UserID string `json:"userId"`
}
Run Code Online (Sandbox Code Playgroud)
它生成如下表(由 DBeaver 生成 UML 并仔细检查是否正确):
CreatedBy我正在尝试向和列添加外键UpdatedBy,以便它们必须指向现有的Profile. 所以我将以下字段添加到类型中BaseModel:
CreatedByProfile *Profile `json:"-" gorm:"foreignKey:CreatedBy"`
Run Code Online (Sandbox Code Playgroud)
我希望为每个模型创建外键,该模型BaseModel是该表的一部分并指向该Profiles表。然而,这只能让FK上场Profiles。
问题的最小重现:
package main
import (
"encoding/json"
"time"
"github.com/lib/pq"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type BaseModel struct {
ID string `json:"id" gorm:"type:uuid;primarykey;default:uuid_generate_v4()"`
InstanceVersion int `json:"instanceVersion"`
CreatedAt time.Time `json:"createdAt" gorm:"type:timestamp"`
UpdatedAt time.Time `json:"updatedAt" gorm:"type:timestamp"`
DeletedAt *time.Time `json:"deletedAt,omitempty" gorm:"type:timestamp" sql:"index"`
CreatedBy string `json:"createdBy"`
UpdatedBy string `json:"updatedBy"`
DeletedBy *string `json:"deletedBy,omitempty"`
MetaData json.RawMessage `json:"metadata" gorm:"type:jsonb;default:'{}'"`
CreatedByProfile *Profile `json:"-" gorm:"foreignKey:CreatedBy"`
}
type ActivityType string
type Activity struct {
Base BaseModel `gorm:"embedded"`
Type ActivityType `json:"type"`
Message string `json:"message"`
Content string `json:"content"`
ImageUrl string `json:"imageUrl"`
DisplayProfileIds pq.StringArray `json:"displayProfileIds" gorm:"type:uuid[]"`
RecipientProfileIds pq.StringArray `json:"recipientProfileIds" gorm:"-"`
// Preload
ActivityProfiles []*ActivityProfile `json:"activityProfiles"` // has many
}
type ActivityProfile struct {
Base BaseModel `gorm:"embedded"`
ReadAt *time.Time `json:"readAt,omitempty" gorm:"type:timestamp" sql:"index"`
Route string `json:"route"`
ActivityID string `json:"activityId"`
ProfileID string `json:"profileId"`
// Preload
Activity *Activity `json:"activity"` // belongs to
Profile *Profile `json:"profile"` // belongs to
}
type Profile struct {
BaseModel
Name string `json:"name"`
UserID string `json:"userId"`
}
func main() {
db, err := gorm.Open(postgres.Open("host=localhost port=5432 user=corey dbname=corey password= sslmode=disable"))
if err != nil {
panic(err)
}
models := []interface{}{
&Activity{},
&ActivityProfile{},
&Profile{},
}
err = db.AutoMigrate(models...)
if err != nil {
panic(err)
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过使用gorm:"embedded"标签而不是嵌套结构,但没有帮助。这个问题中的任何内容都没有帮助:DB.Model(...).AddForeignKey(...)不再存在,这些db.Migrator().CreateConstraint(...)行不起作用(它如何知道哪一列是 FK 以及它与其他类型的哪一列匹配?我是否必须运行这两行?这怎么可能曾经可能工作吗?!?),我不需要OnUpdate或OnDelete限制,只是外键。
如果我将该CreatedByProfile字段放在 上Activity,那么我会得到一个 FK,其中是 100% 向后的Profile.CreatedByFK 。Activity.ID
我可以将此字段添加到我的Profile模型中:
Activities []*Activity `json:"-" gorm:"foreignKey:CreatedBy"`
Run Code Online (Sandbox Code Playgroud)
它创建了我想要的 FK,但我实际上并不希望该字段出现在模型上。另外,我必须为数据库中的每个模型添加这个不必要的样板(并且_字段不会以 FK 的形式结束)。
如何让 Gorm 做简单的事情,比如创建外键,而不用未使用的字段装饰我的模型?
| 归档时间: |
|
| 查看次数: |
2294 次 |
| 最近记录: |