为了账号安全,请及时绑定邮箱和手机立即绑定

gorm 中的外键约束

gorm 中的外键约束

Go
噜噜哒 2022-08-24 11:42:26
我想创建一个预订-舱位关系,在这个关系中,每个预订只能分配一个舱位。type Class struct {    Id   int    `json:"id"`    Name string `json:"name"`}type Booking struct {    Id      int    `json:"id"`    User    string `json:"user"`    Members int    `json:"members"`    ClassId int    `json:"classid"`}我知道它类似于gorm在这里解释的“属于”关系,https://gorm.io/docs/belongs_to.html 但我想知道是否有可能在不定义Booking模型中的Class类型字段的情况下实现“外键约束”(只有ClassId int)。为了确保使用不存在的 ClassId-s,我定义了函数:func Find(slice []int, val int) bool {    for _, item := range slice {        if item == val {            return true        }    }    return false}func GetClassKeys(d *gorm.DB) []int {    var keys []int    rows, _ := d.Raw(`SELECT id                        FROM classes`).Rows()    defer rows.Close()    for rows.Next() {        var key int        rows.Scan(&key)        keys = append(keys, key)    }    return keys}并在创建/更新预订之前执行此检查:if !Find(GetClassKeys(db), booking.ClassId) {    log.Println("Wrong class id value")    return}但这不能处理删除类id的情况(常规数据库会自动执行此操作)。我想知道有没有办法通过简单地在用户模型中引用Class的主键来实现与gorm的正常数据库外键功能?提前致谢
查看完整描述

1 回答

?
喵喔喔

TA贡献1735条经验 获得超5个赞

我不认为迁移器工具会帮助你,因为它假设你将使用默认的Gorm模式来定义关系,并且你已经明确决定不使用这些模式。


剩下的唯一选择是自己管理约束,要么通过SQL脚本,要么通过更简单的,在调用旁边运行的一些自定义查询:AutoMigrate


import "gorm.io/gorm/clause"


// somewhere you must be calling

db.AutoMigrate(&Class{}, &Booking{})


// then you'd have:

constraint := "fk_booking_classid"

var count int64

err := db.Raw(

    "SELECT count(*) FROM INFORMATION_SCHEMA.table_constraints WHERE constraint_schema = ? AND table_name = ? AND constraint_name = ?", 

    db.Migrator().CurrentDatabase(),

    "bookings",

    constraint,

).Scan(&count).Error

// handle error


if (count == 0) {

    err := db.Exec(

        "ALTER TABLE bookings ADD CONSTRAINT ? FOREIGN KEY class_id REFERENCES classes(id)",

        clause.Table{Name: constraint},

    ).Error

    // handle error

}

当然,这否定了自动迁移的优势(这意味着当字段名称等内容发生变化时,约束将在不更改迁移代码的情况下更新)。


我会看看为什么你不想像gorm预期的那样定义外键,因为这闻起来像你试图直接使用数据库模型作为JSON API请求/响应模型,这通常不会导致一个好的结束:)


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 190 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信