【问题标题】:Foreign Key Constraint in gormgorm中的外键约束
【发布时间】:2021-07-02 00:34:16
【问题描述】:

我想创建一个 Booking-Class 关系,每个 Booking 只能分配一个 Class。

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诠释)。为了确保使用不存在的 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 实现正常的数据库外键功能?提前致谢

【问题讨论】:

  • department 来自哪里?顶部的两个结构中没有提到它?
  • @Christian 抱歉打错了,我的意思是班级。编辑了帖子。谢谢!
  • 您应该能够使用迁移器界面手动添加约束:gorm.io/docs/migration.html#Constraints(注意:我没有成功地做到这一点,因为文档有点稀疏)

标签: go foreign-keys go-gorm


【解决方案1】:

我认为 Migrator 工具不会帮助您,因为它假定您将使用默认的 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 请求/响应模型,而这通常不会不会有好的结局:)

【讨论】:

    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 2011-08-30
    • 2013-05-03
    • 2011-08-18
    相关资源
    最近更新 更多